rev Mai 2024
Partie détails du
Développement :
* Prototype
Hardware Chaudiere (27/04/2023)
* Tests
Hardware sur Carte (PCB) Chaudiere(28/07/2023)
* 1er Test Hardware
concluant (29/07/2023)
* Liaison
BlueTooth Carte Chaudiere <--> Terminal PC YAT (26/08/2023)
* Affichage
LCD 4x20 cars
* Egalisation
des 3 sondes de temperture DS18B20
=======
TESTS divers
Liens:
Présentation du PIC
18F27K42 et Base Hardware utilisée
Real Time Clock RTC DS3231 (avec MikroC)
Timer0 utilisé en mode pooling
Eeprom
24LC256
Test LCD 2x16 cars , en liaison I2C via interface PCF8574
(dip16).
07/04/2023
Schema :
Utilisation de : BASE PIC18F27K42 pour
les premiers tests
Liaison I2C1 PIC18F27K2
RC3 =SCL et RC4=SDA , vers
interface PCF8574 I2C / 8 E/S paralleles
Usage de l'I2C Hardware
Adresse I2C :
Adresse device de base du LCD = 0x20H ( type LCD1602 avec
driver LCD_HD44780.pdf
avec les pins A0,A1,A2 du PCF8574 à zéro , le
complement d'adresse et 0 , donc
adresse 7 bits = 0x20H en ecriture ( adresse 8bits 0x40
!)
I2C Speed=100Khz* :
I2C1CLK = 0x03; // MFINTOSC =500KHz par defaut
mais ATTENTION l'horloge
choisie est divisée par 5 (si FME=0)
RC3 SCLK= 500 / 5=100Khz
ou divisée par 4 si FME=1 , soit 500 /4=125Khz
* possibilté d'utililiser la sortie postscaler Timer 2
comme horloge I2C,
I2C1CLK = 0x06; ///0110 TMR2 post scaled output
avec FME=0 ; SLCK = 168.42Khz / 5 =33.68Khz ..OK
avec FME=1 ; SCLK = 168.42Kz/4= 41.98Khz..OK
L'init du LCD en mode 4 bits...
doit demarrer en mode 8 bits ,pour passer ensuite en mode
4 bits.
Les datas sont alors presentées en MSB sortie PCF8574.
8 bits sont envoyés en 2 tems, MSB puis LSB
Le LSB est decalé à gauche pour pouvoir se retouver sur
les pins P7..P4.
Pins de commande
P3 La pin BL , reglage luminosité arriere plan LCD est
fixée via une pull-up au +Vcc (anode Led) et BL (cathode
led) au 0V
P2 pin ENable
P1 R/W n'est pas utilisé..on ne fait pas de Lecture du
LCD, R/W LCD au Gnd.
P0 R/S choix RS=0 => Cde ou RS=1 => Data
La Pin V0 peut recevoir un reglage potentiometrique (curseur
potar) ou une R fixe vers Gnd pour le reglage du
contraste.
Fonctions I2C1 Hardware:
void Init_I2C (void);
void I2C1_Write1ByteRegister(i2c1_address_t address, uint8_t
reg, uint8_t data);
void I2C_PCF8574_Write(unsigned char Addr , unsigned char
value);
Fonctions I2C1 PCF8754 pour LCD2x16
void LCD_init(void);
void LCD_putcmd(unsigned char d,unsigned char cmdtype);
void LCD_putch(unsigned char d);
void LCD_puts(char *s);
void LCD_putsRom(const char *s);
void LCD_Write_CText(const char *txt) ;
void Erase_Line(int L);
void LCD_At(unsigned char Ligne,unsigned char col);
void LCD_Write_Text_At(unsigned char Ligne,unsigned char
col, char * t1);
void LCD_Write_CText_At(unsigned char Ligne,unsigned char
col,const char * t1);
void LCD_Cmd(unsigned char d);
void LCD_Load_Custom_Chars(unsigned char Set,int bavard);
Col = 1 à 16
Line = 1 ou 2
3 Jeux de 8 caracteres spéciaux (en 5x8)
avec 1 seul à la fois, chargé en CGRAM du LCD
sur la version LCD 2x16 !
![]() |
Software MPLABX XC8:
LCD + 1 seule sonde température DS18B20
_18F27K42_LCD_PCF8574_I2C_1xDS18B20_2023-0407_X.hex
resultat sur terminal YAT :
06/06/2023
Affichage prévu maintenant sur un
LCD de 4x20 (datasheet)
Theorie :
Affichage Réel (sur Prototype)
Rafraichit dans la boucle de fond programme
Caractere speciaux en CGRAM : 1 seul jeu de
caracteres
sans barres, barre G V,barre D Verticale , barres G et D
Verticales
Barre_used, sigles Fleches Vert. vers le Haut et vers le
bas, et le sigle Degré en 8em position
sigles * et > déja existant en ROM LCD
nota:
Marche Brûleur (Position L1C15) signalé par alternance, . et *
devant "Chd" , sinon .
fixe pour brûleur à l'arret.
separateur décimal valeurs flottantes (en decimales)
remplacé par le sigle degré ° ( en L1C7 , L2C7, L2C15,L2C19)
nouvelle definition caracteres
speciaux en CGRAM
const unsigned char LCD_Custom_Chars_Set1[64]
=
{
//---------- set #1 ------------------
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // vide!
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // Barre_V_G
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, // Barre_V_D
0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B, // Barre_VGD
0x0A,0x04,0x02,0x04,0x08,0x04,0x0A,0x00, // Barre_used
0x04,0x0E,0x1F,0x04,0x04,0x04,0x04,0x00, // Fleche_H
0x04,0x04,0x04,0x04,0x1F,0x0E,0x04,0x00, // Fleche_B
0x1C,0x14,0x1C,0x00,0x00,0x00,0x00,0x00 // Degré celcius
};
modif affichage en flottant :
point décimal remplacé par °
void
Affiche_LCD_Repos() // rev 02-05-2023
{
unsigned char n1;
if(n1>2) n1=0;
LCD_Cmd(LCD_HOME);__delay_ms(100);
sprintf(CRam1,"Ext %3.1f Chd %3.1f",F1,F3);
*(CRam1+6)=7;*(CRam1+18)=7;//
remplacement . par sigle degré C
LCD_Write_Text_At(1,1,CRam1);
if (Etat_Bruleur==0)
LCD_Write_CText_At(1,10,"...");
else
{ // si bruleur ON
LCD_Chr_At(1,10+n1,'>');
n1++;
if (n1>2) n1=0;
}
sprintf(CRam1,"Int %3.1f %2s %3.1f+%2.1f",F2,Confort[Choix_Conf_Eco],Consigne,CompensationR);
*(CRam1+6)=6;*(CRam1+14)=7;*(CRam1+18)=7;
// remplacement . par sigle degré C
LCD_Write_Text_At(2,1,CRam1);
sprintf(CRam1,"%c%c:%c%c m ",time[0],time[1],time[3],time[4]);
LCD_Write_Text_At(3,1,CRam1);
sprintf(CRam1,"D %c%c am> ",*(All_Jour_Semaine+jS*2),*(All_Jour_Semaine+jS*2
+1 ) );
LCD_Write_Text_At(4,1,CRam1);
};
Le LCD Affiche :
les 3 mesures de températures DS18B20 ...corrigées (via
la procedure "Equalisation")
le mode Confor Cf ou
Economique Ec.....
en L2.. 10,11
Heure et Minutes en L3.. 12345
Nom du programme en cours en L4. 1
initiales du nom du jour en cours en L4 ..3,4
Le programme horaire matin en L3......... 9..20
Le programme horaire Apres Midi en L4 9..20
etat bruleur en L1... 10,11,12 "..." = arret ,sinon
sigle ">" dynamique en 10,11,12
Carateres disponibles su ce LCD 4x20:
pour affichage sur TERMINAL ET LCD
sprintf(txt,"
T1.INTER.= %5.3f%cC",F1,176); // 176 ° sur terminal
Print(txt);CRLF1();
*(txt+17)=7; // degre C
LCD_Write_Text_At(2,1,txt);
ou ,pour Affichage Seulement sur LCD
sprintf(txt,"
T1.INTER.= %5.3f%cC",F1,223); // ° sur ROM LCD
LCD_Write_Text_At(2,1,txt);
Test
avec 1 seul capteur OWS DS18B20
DS18B20
datasheet
utilisation de la pin 2 du PIC : RA0
Le capteur est alimenté via +VCC et Gnd
Le signal de sortie va sur RA0, avec une pull_up de 2.7K
au +Vcc
Utilisation de la librairie :
https://github.com/simonbarker/pic-libraries/blob/master/onewire.h
avec quelques amenagements ,adaptations au 18F27K42.
#define
onewirePin PORTAbits.RA0
#define onewirePinDirection TRISAbits.TRISA0 //0 = output,
1 = input
au niveau de l'init Hardware du PIC
RA0 Open Collecteur via
// ODx registers
ODCONA = 0x01; // 0x01 => open drain sur RA0 OWS sensor
Les fonctions liées au protocole OWS
void
onewireWriteBit(int b);
unsigned char onewireReadBit();
unsigned char onewireInit();
unsigned char onewireReadByte();
void onewireWriteByte(char data);
unsigned char onewireCRC(unsigned char* addr, unsigned
char len);
Librairie associée au DS18B20
https://github.com/simonbarker/pic-libraries/blob/master/DS18B20.h
Les fonctions liées à cette librairie :
void
broadcastConvert();
float getTemperature(unsigned char* address);
int getTemperatureInt(unsigned char* address);
void printSingleAddress();
Avec cette librairie, c'est assez simple:
La fonction Broadcast verifie si il y a un capteur OWS
présent sur la ligne (RA0)
la fonction getTemperature effectue les
différentes etapes du protocole OWS
pour dialoguer avec le capteur, récupere son Numero d'ID#
, et le retourne dans le tableau pointé par address,
Ce ID# , numéro d'identification est unique à chaque
capteur DS18B20
Le 1er element étant 0x28 => famille DS18B20 , la
suite c'est le ID#
La fonction retourne la mesure de temperature en flottant
...avec une mesure initiale sur 12 bits => +- 0,0625°C
exemple:
Config et Init One Wire
Test présence d'un capteur O.W.S. sur RA0
Sensor Datas :
Code Famille : DS18B20
OWS ID# = AA.42.65.26.13.02.B6.
CRC = B6
Mesure DS18B20
#1 :
00000 temp = 18.812 ° C
00001 temp = 18.812 ° C
00002 temp = 18.812 ° C
00003 temp = 19.187 ° C
00004 temp = 19.500 ° C
00005 temp = 19.562 ° C
SOFTWARE :
regroupe les librairies I2C, OWS, DS18B20
MCC n'est pas utilisé..
_18F27K42_LCD_PCF8574_I2C_1xDS18B20_2023-0407_X.zip
main.c renommé
main__18F27K42_LCD_PCF8574_I2C_1xDS18B20_2023-0407_X.c
_18F27K42_LCD_PCF8574_I2C_1xDS18B20_2023-0407_X.hex
Test Lecture 3 capteurs DS18B20
sur 1 seul Bus OWS
Au niveau hardware, Les 3 sont connectés
ensembles sur le meme BUS OWS ( fil sur la pin RA0 du PIC)
!
Dans ce cas de figure, il faut imperativement
connaitre le ID# de chaque Sonde DS18B20
ID# Indentification Data number , equivalant à une
adresse MAC, pour que le bus One Wire System accede
seulement à celui.
en ignorant les 2 autres .
Le programme comporte donc une séquence pour lire et
afficher l'adresse de chaque sonde DS18B20 et d'en
memoriser l'adresse (ID#)
dans une table de travail en RAM et en Eeeprom
Une fois réalisé, on aura plus besoin de refaire cette
manip, si les ID~sont en eeprom
il suffira de relire le contenu Eeeprom .
ATTENTION, SAUF si on change ou interverti l'ordre des
capteurs !
j'ai mis une compilation
conditionelle pour cela (#ifdef Pass_Over) ..mais ce
pourrait etre l'etat d' une PIN particuliere du PIC)
au moment de la programmation ,on pourrait aussi , mettre
directement les ID# en data eeprom , si on les
connait déja !
un flag en position adresse 0 de l'eeprom , indique si
les ID# ont bien été saisi : 99 si ok, sinon 0
// Table
de travail : Adresses des 3 capteurs de
température
unsigned char SENSOR_ADDRESS[4][8]=
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // #1 Data:
FamilyCode 28 ID1= FF4715811603 CRC= 24
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // #2 Data:
FamilyCode 28 ID2= FF83C7641503 CRC= B8
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // #3 Data:
FamilyCode 28 ID3= AA56C1381401 CRC= 40
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // réserve en
option pour une 4em sonde
#endif
};
#include
"Eeprom_PIC.h"
#ifdef Pass_Over
// eeprom config 4 sondes DS18B20
__EEPROM_DATA (99,0,0,0,0,0,0,0);
__EEPROM_DATA (0,0,0,0,0,0,0,0); // 0x0000
__EEPROM_DATA (0x28,0xFF,0x47,0x15,0x81,0x16,0x03,0x24);
// #1 Data: FamilyCode 28 ID1= FF4715811603 CRC= 24
__EEPROM_DATA (0,0,0,0,0,0,0,0); // 0x0010
__EEPROM_DATA (0x28,0xAA,0x42,0x65,0x26,0x13,0x02,0xB6);
// #2 Data: FamilyCode 28 ID2= FF83C7641503 CRC= B8
__EEPROM_DATA (0,0,0,0,0,0,0,0); // 0x0020
__EEPROM_DATA (0x28,0xAA,0x56,0xC1,0x38,0x14,0x01,0x40);
// #3 Data: FamilyCode 28 ID3= AA56C1381401 CRC= 40
__EEPROM_DATA (0,0,0,0,0,0,0,0); // 0X0030
__EEPROM_DATA (0x28,0xAA,0x0D,0x82,0x38,0x14,0x01,0xCD);
// repérée #6 !
__EEPROM_DATA (0,0,0,0,0,0,0,0); // 0x0040
#else
// eeprom config 4 sondes DS18B20
__EEPROM_DATA (0,0,0,0,0,0,0,0); __EEPROM_DATA(0,0,0,0,0,0,0,0);
// 0x0000
__EEPROM_DATA (0,0,0,0,0,0,0,0); __EEPROM_DATA(0,0,0,0,0,0,0,0);
// 0x0010
__EEPROM_DATA (0,0,0,0,0,0,0,0); __EEPROM_DATA(0,0,0,0,0,0,0,0);
// 0x0020
__EEPROM_DATA (0,0,0,0,0,0,0,0); __EEPROM_DATA(0,0,0,0,0,0,0,0);
// 0X0030
__EEPROM_DATA (0,0,0,0,0,0,0,0); __EEPROM_DATA(0,0,0,0,0,0,0,0);
// 0x0040
#endif
fonction utilisée :
void Adresse_Device_DS18B20(int N)
{
int i;
// Onewire reset signal
onewireInit();
//The match ROM command followed by a 64-bit ROM code
sequence allows
//the bus master to address a specific slave device on a
multidrop or single-drop bus.
// Only the slave that exactly matches the 64-bit ROM
code sequence will respond to
// the function command issued by the master
__delay_us(250);
onewireWriteByte( THERM_CMD_MATCHROM); //0x55
for (i=0;i<8;i++)
{
onewireWriteByte(SENSOR_ADDRESS[N-1][i]) ;
__delay_us(250);
}
}
Un dialogue est etablit avec l'operateur pour connecter
individuellement chaque sonde, dans un ordre qui sera
immuable.
Exemple
#ifdef Pass_Over
CPrint(" ATTENTION :
Forçage init EEPROM par programme pendant le
developpement Application,\r\n\
pour eviter une resaisie
systematique des ID# à chaque rechargement de programme\r\n");
#endif
CPrint(" Relecture et visu contenu Eeprom\r\n");
Relecture_Eeprom(1); // parametre 1=> avec visu du
contenu sur le terminal YAT UART1
CRLF1();
__delay_xSec(2);
if (Flag_Eeprom
==99)
{
CPrint(" Parametres en Eeprom restitués OK et
transférés -> table de travail SENSOR_ADDRESS[[] \r\n");
Erase_Line(1); __delay_ms(100);
LCD_putsRom("Restitue Eeprom");
Erase_Line(2); __delay_ms(100);
LCD_putsRom("->3xID DS18B20 ");
__delay_xSec(2);
goto Suite
;
}
//
on a pas le choix !
CPrint(" ATTENTION\r\n Saisie
obligatoire des 3 ID# sondes DS18B20\r\n");
// --- Reconnaissance de l' ID# pour chacune des 3 sondes
DS18B20
CPrint(" Test présence d'un seul capteur O.W.S. à
la fois sur RA0\r\n");
CPrint (" Connecter la SONDE #1, puis appui sur SW0\r\n");
Erase_Line(1); __delay_ms(100);
LCD_putsRom("Connect SONDE #1");
Erase_Line(2); __delay_ms(100);
LCD_putsRom("et appui sur SW0");
while(SW0==1)
{};
__delay_ms(20);
while(SW0==0)
{};
broadcastConvert() ;
CPrint(" Sensor Type, ID# , CRC :\r\n");
printSingleAddress();
Erase_Line(1); __delay_ms(100);
LCD_putsRom("ID#1 sensor ");
Erase_Line(2); __delay_ms(100);
sprintf(CRam1,"%8c",OWS_address);
LCD_Write_Text_At(2,1,CRam1);
__delay_xSec(3);
// la 1ere sonde est forcément validée par defaut !
memcpy(SENSOR_ADDRESS[0],OWS_address,8);
Flag_Eeprom=9; // 9 pour ID#1 90 pour ID#1 et 2 99 pour
les 3 ID
Sauve_Parametres_en_Eeprom() ;
// verification visuelle
Relecture_Eeprom(1);
et ainsi de suite pour la 2em sonde DS18B20
deconnecter la #1, connecrter la #2
....
et pour la 3em sonde DS18B20
deconnecter la #2, connecrter la #3
....
Suite:
// si on arrive directement
ici, c'est que les ID# sont en EEPROM
CPrint (" Connecter les 3 sondes
sur RA0 et appui sur SW0 pour continuer\r\n");
Erase_Line(1); __delay_ms(100);
LCD_putsRom("Connect.les 3 ");
Erase_Line(2); __delay_ms(100);
LCD_putsRom("et appui sur SW0");
__delay_ms(100);
on peut enfin lire la valeur issue des 3 sondes ,via leur
adresse (ID#) respectives:
sur le terminal YAT et LCD 2x16 ( sauf la 3em)
CPrint(" 3
Mesures DS18B20 #1 : \r\n");
do
{
broadcastConvert();
F1= getTemperature(SENSOR_ADDRESS[0]);
sprintf(txt," %05d temp#1. EXTERIEUR = %5.3f %c C \t",i,F1,176);
Print(txt);
sprintf(CRam1,"%3.2f C",F1);
LCD_Write_Text_At(1,10,CRam1);
LCD_Chr_At(1,15,0); // degre C
broadcastConvert();
F1= getTemperature(SENSOR_ADDRESS[1]);
sprintf(txt," temp#2. INTERIEUR = %5.3f %c C \t",F1,176);
Print(txt);
sprintf(CRam1,"%3.2f C",F1);
LCD_Write_Text_At(2,10,CRam1);
LCD_Chr_At(2,15,0); // degre C
broadcastConvert();
F1= getTemperature(SENSOR_ADDRESS[2]);
sprintf(txt," temp#3. EAU = %5.3f %c C \r\n",F1,176);
Print(txt);
// pas d'affichage
avec LCD si LCD 2x16 !! il faudrait un 4x20
SOFTWARE
_18F27K42_LCD_PCF8574_1bus_OWS_3xDS18B20_2023-0411.zip
main_1bus_3xDS18B20_2024-0411.c
_18F27K42_LCD_PCF8574_1bus_3xDS18B20_2023-0412.X.hex
Test Lecture 3
capteurs DS18B20 sur 3 Bus OWS independants
Hardware :
Usage des pins RA0,RA1,RA2 pour connecter les 3 sondes
On a plus besoin de connaitre le ID# d'une sonde, mais il
faut gerer 3 bus OWS independants.
On peut donc facilement remplacer une sonde ,sans modif
software.
gestion du bus OWS
il faut preciser sur quelle pin , quel bus ,on travaille
!
#define
onewirePin PORTAbits.RA0
#define onewirePinDirection TRISAbits.TRISA0 //0 = output,
1 = input
#define onewirePin0 PORTAbits.RA0
#define onewirePinDirection0 TRISAbits.TRISA0 //0 =
output, 1 = input
#define onewirePin1 PORTAbits.RA1
#define onewirePinDirection1 TRISAbits.TRISA1 //0 =
output, 1 = input
#define onewirePin2 PORTAbits.RA2
#define onewirePinDirection2 TRISAbits.TRISA2 //0 =
output, 1 = inpu
Les fonctions de base sont donc dupliqués 3 fois !
OWS software en mode bit bang ..
Adaptation Librairie OWS :
OneWire_2023.c
OneWire_2023.h
exemple : BUS#1 sur RA0:
Au niveau du bit :
void
onewireWriteBit_0(int b) { //b = b & 0x01; if (b>0) { // Write '1' bit onewirePinDirection0 = 0; onewirePin0 = 0; __delay_us(5); onewirePinDirection0=1; __delay_us(60); } else { // Write '0' bit onewirePinDirection0 = 0; onewirePin0 = 0; __delay_us(70); onewirePinDirection0 = 1; __delay_us(2); } } |
unsigned
char onewireReadBit_0() { unsigned char result; onewirePinDirection0 = 0; onewirePin0 = 0; __delay_us(1); onewirePinDirection0 = 1; __delay_us(5); result = onewirePin0; __delay_us(55); return result; } |
au niveau
BYTE (octet)
unsigned char onewireReadByte_0() { unsigned char result = 0; unsigned char loop0; for ( loop0 = 0; loop0 < 8; loop0++) { // shift the result to get it ready for the next bit result >>= 1; // if result is one, then set MS bit if (onewireReadBit_0()>0) result |= 0x80; } return result; } |
void onewireWriteByte_0(char datax) { unsigned char loop; for ( loop = 0; loop < 8; loop++) { onewireWriteBit_0(datax & 0x01); datax >>= 1; } } |
Il faut ensuite gerer le Protocole lié au capteur
DS18B20 :
Librairie :
DS18B20_2023.c
DS18B20_2023.h
exemple pour Sonde #1 , connectée sur RA0
float getTemperature1()
{
unsigned char i;
float temperature0;
unsigned char scratchPad[9] = {0,0,0,0,0,0,0,0,0};
// for (i=0;i<9;i++) scratchPad[i] =0;
onewireInit_0();
onewireWriteByte_0(0xCC);
onewireWriteByte_0(0x44);
#ifdef
AVEC_TEMPO
__delay_us(485);
#else
// 780mS en 12b avec le test bit ci dessous
while (1) {
if (onewireReadBit_0()) break;
}
#endif
onewireInit_0();
onewireWriteByte_0(0xCC);
onewireWriteByte_0(0xBE);
for (i = 0; i < 2; i++) scratchPad[i] = onewireReadByte_0();
onewireInit_0();
temperature0 =( ( scratchPad[1] * 256.0) + scratchPad[0]
)*Resolution ;
return temperature0;
}
à noter :
avec #define AVEC_TEMPO
, la mesure peut
etre acquise en 100mS au lieu de > 750mS avec le Test
bit
Je n'ai trouvé aucune claire explication sur ce point
Nota :
car un test , avec une acquisition en boucle des 3
mesures ..j'obtiens les 3 chaque 300 mS!
on ne retouve pas la necessité des 750mS annoncées sur
la data sheet avec le test de bit fin de conversion.
CPrint("
Mesures 3 temperatures DS18B20 sur 3 bus OWS : \r\n");
CRLF1();
sprintf(txt," %05d\r\n",Nb_Boucles);
Print(txt);
F1= getTemperature1();
sprintf(txt," T1.INTER.= %5.3f%c C",F1,176);
Print(txt);CRLF1();
sprintf(CRam1,"%3.2f C",F1);
LCD_Write_Text_At(1,12,CRam1);
LCD_Chr_At(1,17,0); // degre C
F2= getTemperature2();
sprintf(txt," T2.EXTER.= %5.3f %cC",F2,176);
Print(txt);CRLF1();
sprintf(CRam1,"%3.2f C",F2);
LCD_Write_Text_At(2,12,CRam1);
LCD_Chr_At(2,17,0); // degre C
F3= getTemperature3();
sprintf(txt," T3.EAU = %5.3f %cC",F3,176);
Print(txt); CRLF1();
sprintf(CRam1,"%3.2f C",F3);
LCD_Write_Text_At(3,12,CRam1);
LCD_Chr_At(3,17,0); // degre C
* nota : ici le LCD est un 4x20
cars !
Resultats:
(2.084)
Mesures 3 temperatures DS18B20 sur 3 bus OWS :
(0.017)
(0.000) 00000
(0.000) T1.INTER.= 19.375° C
(0.090) T2.EXTER.= 20.000 °C
(0.095) T3.EAU = 19.250 °C
(0.084)
(0.999) 00001
(0.084) T1.INTER.= 19.375° C
(0.033) T2.EXTER.= 19.937 °C
(0.082) T3.EAU = 19.250 °C
(0.093)
(0.991) 00002
(0.087) T1.INTER.= 19.375° C
(0.036) T2.EXTER.= 19.937 °C
(0.078) T3.EAU = 19.250 °C
SOFTWARE :
main_3bus_3xDS18B20_11b_LCD4x20_IT_RB0_RTC_2023-0418.c
_18F27K42_LCD_PCF8574_3bus_3xDS18B20_RTC_IT_RB0_UART_2023-0418.X.hex
Test des B.P. (switches SW0..SW5 ) en mode pooling.
noat : hardware sur breadboard
... ce test n'est pas reconduit dans l'application finale
!
mais doitt servir au 1er test hardware de la carte
electronique avec MCU.
donc compilation conditionelle !
Rappel :
* SWx au repos= 1 , actionné=0
* Dans ce test, l'interrupt INT0 (RB0) n'est pas
utilisée .( ni les IOCx !)
l'usage de #define , équivalent à une macro , permet d
'isoler directement le bit representant le BP actionné
#define SW0 ( PORTB & 0x02)
>>1 // SW0_PRM Menu Paramètres
#define SW1 ( PORTB & 0x04)>>2 // SW1 CFE
Alterner Confort / Eco
#define SW2 ( PORTB & 0x08)>>3 // SW2_POS
Augmenter Consignes
#define SW3 ( PORTB & 0x10)>>4 // SW3_NEG
Diminuer Consignes
#define SW4 ( PORTB & 0x20)>>5 // SW4_PRG Menu
Prog Hebdo
#define SW5 ( PORTB & 0x40)>>6 // SW5_HGR Menu
Hebdo
#ifdef With_TEST_6_BP
CPrint(" Special test appui des 6
BP : SW0..SW5\r\n");
i=0;
do
{
sprintf(CRam1," %5d PORTB %02X SW5=% 1x SW4=% 1x SW3=%
1x SW2=% 1x SW1=% 1x SW0=% 1x\r\n",i,PORTB,SW5,SW4,SW3,SW2,SW1,SW0);
Print(CRam1);
__delay_ms(100);
i++;
}
while (i<1000);
#endif
Resultat sur terminal YAT :
*nota:
le SW5
sur pin RB6, n'est pas cablé sur
mon prototype ...
il est à 0
,car le PIckit4 est resté connecté sur l'ICSP ...RB7 et
RB6 !
Special test appui des 6 BP : SW0..SW5
0 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
1 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
2 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
...etc ...
8 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
9 PORTB 3C SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=0
10 PORTB 3C SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=0
11 PORTB 3C SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=0
12 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
13 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
14 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
..... etc
33 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
34 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
35 PORTB 36 SW5=0 SW4=1 SW3=1 SW2=0 SW1=1 SW0=1
36 PORTB 36 SW5=0 SW4=1 SW3=1 SW2=0 SW1=1 SW0=1
37 PORTB 36 SW5=0 SW4=1 SW3=1 SW2=0 SW1=1
SW0=1
38 PORTB 36 SW5=0 SW4=1 SW3=1 SW2=0 SW1=1 SW0=1
39 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1
SW0=1
40 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
.... etc ....
46 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1
SW1=1 SW0=1
47 PORTB 2E SW5=0 SW4=1 SW3=0 SW2=1
SW1=1 SW0=1
48 PORTB 2E SW5=0 SW4=1 SW3=0 SW2=1 SW1=1 SW0=1
49 PORTB 2E SW5=0 SW4=1 SW3=0 SW2=1 SW1=1 SW0=1
50 PORTB 2E SW5=0 SW4=1 SW3=0 SW2=1 SW1=1 SW0=1
51 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1
SW1=1 SW0=1
52 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
...etc
60 PORTB 3F SW5=0 SW4=1
SW3=1 SW2=1 SW1=1 SW0=1
61 PORTB 1E SW5=0
SW4=0 SW3=1 SW2=1 SW1=1 SW0=1
62 PORTB 1E SW5=0 SW4=0 SW3=1 SW2=1 SW1=1 SW0=1
63 PORTB 1E SW5=0 SW4=0 SW3=1 SW2=1 SW1=1 SW0=1
64 PORTB 1E SW5=0 SW4=0 SW3=1 SW2=1 SW1=1 SW0=1
65 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
66 PORTB 3F SW5=0 SW4=1 SW3=1 SW2=1 SW1=1 SW0=1
SW5 non testé,
absent !
si on cable SW5 , ne pas oublier de déconnecter le
PICKIT4 de l' ISP.
Software :
main_3bus_3xDS18B20_11b_LCD4x20_IT_RB0_RTC_Tests_6xBP_en_pooling_2023-0426.c
_18F27K42_LCD_PCF8574_DS18B20_Test_6_BP_en_pooling_2023.X.hex
Nota : j'utilise le même dossier pour tous mes tests ,
mais le programme principal se nomme main.c
dans tous les cas
je renomme donc celui ci ,pour bien definir son role dans
les cas particuliers avec un nom le plus explicite
possible .
de même pour le fichier *.hex
Equalisation
ou Auto Calibration relative entre 3 capteurs DS18B20
Description:
rev 11/05/2023
On part sur le postula suivant :
un capteur DS18B20 a une précision de +-0.5°C en
valeur absolue.
En prenant la moyenne de 3 mesures capteurs mesurant la
même température ambiante
on a une valeur pouvant se rapprocher de la réalité ..
C'est donc plus une EQUALISATION qu'une CALIBRATION...
car encore
faudrait-il avoir un thermomètre bien plus précis que
les sondes elles-mêmes.
Cette procédure ne peut plus s'appliquer dans le
contexte utilisation, car les sondes sont affectées
à des endroits de mesure très différents (extérieur,
ambiante, eau) une fois que l'application est en service.
et donc, on a plus la possibilité de réunir les 3 capteurs
ensemble..
ou alors, les débrancher et réunir spécialement pour
cette opération. si changement de capteur.
Le BP SW6 (sur pin RC5) est non accessible directement en
facade, il est affecté uniquement à cette opération au
lancement du programme..
Les 2 BP : Reset et SW6 doivent etre maintenus appuyés en
même temps au lancement du programme..
On relache seulement le BP Reset ..pour lancer le
programme
Le programme surveille dès lors, l'etat de SW6 , et
chronometre sa durée de maintien appuyé
Durée mesurée au relachement de SW6
Il faut l'appuyer pendant plus de 2sec
pour pouvoir réaliser ensuite l'Egalisation .
sinon ..
on passe outre...=> vers la boucle principale du
programme
Un drapeau est armé pour
preciser qu'on a fait la demande d'Egalisation
car il faut tout d'abord
réaliser les operations d'initialisations ( UART,I2C,OWS,LCD ..tables,variables..)
Apres ces operations ( durée quelques secondes maxi)
si le flag de demande a été armé, Le LCD affiche :
valider par appui SW6 > 2sec
Demande acceptée
Le programme effectue alors l'acquisition des 3 mesures
DS18B20 (F1,F2,F3)
En calcule la moyenne (F0=(F1+F2+F3)/3.0;)
et les écarts respectifs de chacune par rapport à cette
moyenne
Txcor[0]=F0-F1;
Txcor[1]=F0-F2;
Txcor[2]=F0-F3;
Résultats affichés sur LCD
La correction est déduite de la la moyenne des 3
mesures - la mesure brute en cours
Une fois les corrections mesurées
.
il FAUT VALIDER ensuite ,par appui sur SW6
pendant >=2sec
Les corrections (valeurs en flottant) sont alors
stockées en Eeprom .
sinon on ré-utilisera celles qui étaient déja en
Eeprom PIC.
On attend l'appui sur BP Reset
pour Sortir d'une boucle infinie
dans laquelle on fait clignoter la led Rouge
*******************************************************************************
Un nouvel appui sur
BP Reset relance le
programme
qui apres les initialisations, relira les corrections qui
ont été sauvegardées précédement en Eeprom
on rajoute alors les corrections aux mesures brutes
capteur DS18B20
Affichage des resultats APRES application de l'EGALISATION
Nota : Les
mesures sont instantanées et donc à + - 1 bit de
résolution soit +- 0,0625°C
nota: au 1er chargement du programme, les 3 corrections
sont à 0.0 ...ainsi que dans l'eeprom.
il faut donc faire cet auto-étalonnage au moins
1 fois .... ou s'en passer !
(au meme titre que l'Intialisation de la RTC DS3231 d'ailleurs!
,qui est vide au depart)
L'auto-Etalonnage doit être proscrit si l'application
est en usage ...
mais n'est proposée que sur Reset ou coupure
alimentation ...et si on maintient appuyé SW6 > 2sec
(au lancement programme)
Une autre
possibilité d'entrer dans ce mode Auto-Calibration
serait via le dialogue UART
ex: si le PIC reçoit le message "Auto-Calibration"
envoyé par un terminal PC ou via bluetooth.
(au meme titre d'ailleurs que pour la remise à data et
heure de la RTC )
ainsi que d'autres possibilités comme le chargement d'un
programme de 48 demi heures.
Nota sur EEPROM:
Une table de travail , de 3 flottants en RAM TxCorr[3] contiendra les corrections utilisées par l'application.
Zone Eeprom réservées pour les 3 corrections capteurs:
La valeur de correction est un nombre flottant (sur 32bits)
occupe donc 4 bytes (octets)
correction
1 : 0x0030 ...0x0033
correction 2 : 0x0034 ...0x0037
correction 3 : 0x0038 ...0x003B
Pour manipuler les valeurs en eeprom (exprimées en octet
ou Char) ,
un pointeur sur l'adresse de la correction en
flottant facilite les choses.
ex: correction F0= 0.210 (°C)
pf=&F0;
*(pf), * (pf+1), *(pf+2), *(pF+3) permet d'acceder à
chaun des bytes constituant la valeur F1 exprimée en
flottant
qui seront stockés à partir de Eeprom 0x0030 ...0x0033
La recuperation des données Eeprom se fait en sens
inverse
.. 4 x (lecture eeprom et ecriture à l'adresse pointée
par *pf. qui s'incremente)
Nota :
avant de tester si un BP est appuyé on s'assure qu'il ne
l'est pas déja , afin de pouvoir chronometrer sa durée
d'appui.
L'Equalisation se fait pratiquement
au 1/1000em de degré (précision de
calcul) !
L'affichage terminal est ensuite réduit à 2
décimales (.... résolution capteur +-0,0625°C)
L'affichage LCD à 1 décimale
Software :
// test demande
equalisation
Demande_Equalisation=0;
Duree_Appui=0;
while (SW6==0)
{
__delay_ms(100);
__asm("btg LATA,6"); // led vert
Duree_Appui++;
}
if (Duree_Appui>19)
{
Demande_Equalisation=1;
// si le flage est monté, on s'en occupe plus loin dans
le programme
LED_vert=ON;// feu fixe eteint ( car ma led est tirée au
+VCC !!!)
}
--------------------------------------------------------------------------
void Equalisation_3_DS18B20(void)
{
CPrint(" Demande AUTO_etalonnage des 3 sondes DS18B20\r\n");
CPrint(" elles doiveent etre reliees mecaniquement
ensembles (meme temperature ambiante)\r\n");
sprintf(CRam1," Attente relache SW6 .. \r\n");
Print (CRam1);
LCD_Cmd(LCD_CLEAR);
LCD_Write_CText_At(1,1,"Relacher SW6 ");
while(SW6==0); // attente relache SW6
//gabarit 12345678901234567890
LCD_Cmd(LCD_CLEAR);
LCD_Write_CText_At(1,1,"Demande EGALISATION ");
LCD_Write_CText_At(2,1,"Les sondes doivent ");
LCD_Write_CText_At(3,1,"etre liees ensemble ");
LCD_Write_CText_At(4,1,"Valider par SW6>2sec");
// Attente validation par SW6 appyué > sec
// les 2 leds clignotes en alternance
LED_vert=1;
LED_rouge=0;
while (SW6==1)
{ __asm("btg LATA,6"); // LED_verte
__asm("btg LATA,4"); // LED_rouge
__delay_ms(20);
}
i=0;
while (SW6==0) // duree BP appuye
{ __delay_ms(100);
i++;
__asm("btg LATA,6"); // LED_verte
__asm("btg LATA,4"); // LED_rouge
if (i>20) break;
}
if (i<20)
{
Erase_Line(1);
Erase_Line(2); // 12345678901234567890
LCD_Write_CText_At(3,1,"Delay SW6 trop court");
LCD_Write_CText_At(4,1,"Demande abortee !.. ");
__delay_xSec(4);
Demande_Equalisation=0;
__asm("reset");
}
LCD_Write_CText_At(4,1,"Demande Acceptee ..");
__delay_xSec(3);
// Affiche_3_mesures_DS18B20_sur_LCD;(0);
// 12345678901234567890
CPrint("Mesures brutes \r\n");
LCD_Cmd(LCD_CLEAR);
F1= getTemperature1();
// 12345678901234567890
sprintf(txt," T1.INTER.= %5.3f%cC",F1,176);
Print(txt);CRLF1();
*(txt+17)=6; // degre C
LCD_Write_Text_At(2,1,txt);
F2= getTemperature2();
sprintf(txt," T2.EXTER.= %5.3f%cC",F2,176);
Print(txt);CRLF1();
*(txt+17)=6; // degre C
LCD_Write_Text_At(3,1,txt);
F3= getTemperature3();
sprintf(txt," T3.EAU .= %5.3f%cC",F3,176);
Print(txt);CRLF1();
*(txt+17)=6; // degre C
LCD_Write_Text_At(4,1,txt);
__delay_xSec(2);
F0=(F1+F2+F3)/3.0;
// 12345678901234567890
sprintf(txt," MOYENNE .= %5.3f%cC",F0,176);
Print(txt);CRLF1();
*(txt+17)=6; // degre C
LCD_Write_Text_At(1,1,txt);
__delay_xSec(3);
CPrint("Calcul des corrections :\r\n");
Txcor[0]=F0-F1;
Txcor[1]=F0-F2;
Txcor[2]=F0-F3;
CPrint(" Mesures issues de l' Egalisation :\r\n");
// resultats sur LCD
LCD_Cmd(LCD_CLEAR);
// Erase_Line(1);
LCD_Write_CText_At(1,1," Results Egalisation");
Erase_Line(2);
//gabarit 12345678901234567890
sprintf(CRam1,"T1 %3.2f%c corr=%2.2f%c",F1,6,Txcor[0],6);
LCD_Write_Text_At(2,1,CRam1);
// Erase_Line(3);
sprintf(CRam1,"T2 %3.2f%c corr=%2.2f%c",F2,6,Txcor[1],6);
LCD_Write_Text_At(3,1,CRam1);
// Erase_Line(4);
sprintf(CRam1,"T3 %3.2f%c corr=%2.2f%c",F3,6,Txcor[2],6);
LCD_Write_Text_At(4,1,CRam1);
sprintf(txt," T1.INTER = %5.3f%c C T1cor=%2.3f",F1,176,Txcor[0]);
Print(txt);CRLF1();
sprintf(txt," T2.EXT = %5.3f%c C T2cor=%2.3f",F2,176,Txcor[1]);
Print(txt);CRLF1();
sprintf(txt," T3.EAU = %5.3f%c C T3cor=%2.3f",F3,176,Txcor[2]);
Print(txt);CRLF1();
__delay_xSec(4);
LCD_Cmd(LCD_CLEAR); // 123456787901234567890
LCD_Write_CText_At(1,1," Appuyer sur SW6 ");
LCD_Write_CText_At(2,1," pendant > 2 Sec ");
LCD_Write_CText_At(3,1," pour valider ");
CPrint(" Appuyer sur SW6 pendant >2sec pour
valider\r\n");
i=0;
// les 2 leds clignotes en alternance
LED_vert=1;
LED_rouge=0;
while (SW6==1)
{
__asm("btg LATA,6"); // LED_verte
__asm("btg LATA,4"); // LED_rouge
__delay_ms(20);
}
i=0;
while (SW6==0) // duree BP appuye
{ __delay_ms(100);
i++;
__asm("btg LATA,6"); // LED_verte
__asm("btg LATA,4"); // LED_rouge
if (i>20) break;
}
if ( (SW6==0) && (i>19) ) // appui>=2sec
{
LED_vert=1;
LED_rouge=0;
CPrint(" Sauvegardes corrections en Eeprom en 0x0050,
0x0054, 0x0058\r\n");
Sauve_Float_To_Eeprom(Org_Txcor,Txcor[0]);
Sauve_Float_To_Eeprom(Org_Txcor+4,Txcor[1]);
Sauve_Float_To_Eeprom(Org_Txcor+8,Txcor[2]);
CPrint(" Fin Auto etalonage 3 sondes DS18B20\r\n");
LCD_Cmd(LCD_CLEAR);
LCD_Write_CText_At(1,1," FIN...OK.......... ");
// 12345678901234567890
LCD_Write_CText_At(2,1,"Sauve corrections ");
LCD_Write_CText_At(3,1,"dans Eeprom PIC ");
__delay_xSec(3);
}
CPrint(" Rechargement corrections capteurs DS18B20
depuis Eeprom\r\n");
Txcor[0]= Read_Float_from_Eeprom(Org_Txcor);
sprintf(CRam1," Temp 1 corrigee= %5.3f \r\n",F1+Txcor[0]
);
Print(CRam1);
Txcor[1]= Read_Float_from_Eeprom(Org_Txcor+4);
sprintf(CRam1," Temp 2 corrigee= %5.3f \r\n",F2+Txcor[1]
);
Print(CRam1);
Txcor[2]= Read_Float_from_Eeprom(Org_Txcor+8);
sprintf(CRam1," Temp 3 corrigee= %5.3f \r\n",F3+Txcor[2]
);
Print(CRam1);
__delay_xSec(3);
CRLF1();
CPrint ("\r\n Attente remise en place des 3 capteurs,et
RESET pour sortir \r\n");
LED_vert=0;
LCD_Cmd(LCD_CLEAR);
LCD_Write_CText_At(1,1,"EGALISATION terminee");
LCD_Write_CText_At(2,1,"Remettre en place ");
LCD_Write_CText_At(3,1,"Les 3 sondes DS18B20");
LCD_Write_CText_At(4,1,"puis BP RESET ... ");
// attente Reset
while(1) // boucle infinie !
{
__asm("btg LATA,4"); // LED_rouge
__delay_ms(100);
}
}
Résulats sur écran
terminal PC :
Presentation :
PIC18F27K42 + 3x OWS sensor DS18B20 sur RA0,RA1,RA2
Directory :C:\MPLABX_Projects\_18F27K42_LCD_PCF8574_DS18B20_2023.X
Project : _18F27K42_LCD_PCF8574_DS18B20_2023
Source : main.c _2023-0510
Config Internal Fosc 64MHz
Autres : DS18B20_2023.h OneWire_2023.h
LCD_4bits_I2C.h UART1_Functions.h , RTC_DS3231_2023-04.h
Eeprom : Eeprom_PIC_2023.h
RA0,RA1,RA2=3xDS18B20,RA4=led,RA3=SQA,RC6=TX UART1
RB0 interrupt pin, SW0...SW5 + SW6 sur RC5
LCD 4x20 cars + RTC sur bus I2C1 HW : RC3=SCL,RC4=SDA
Compile le May 10 2023 a 20:32:02 UTC
avec version XC8 : 2360 et PACK PIC18F-K_DFP 1.6.125
---
Une demande d'Equalisation a été activée ----
Init_I2C() à 100Khz;
Test presence devices sur Bus I2C1
@ decimal # 78 soit @Device 7bits = 0X27 PCF8754 for LCD
2x16cars
@ decimal # 174 soit @Device 7bits = 0X57 EEPROM 512bytes
@ decimal # 208 soit @Device 7bits = 0X68 RTC DS3231
#1 Active sortie RTC SQW=1Hz:
GO
ok
ATTENTION :
Possibilité de forçage init RTC inhibée pendant les
tests
Re-Lecture et affichage des 8 registres RTC DS3231
Wï 02 Wï 00 22H33M07S
adresse LCD= 39 soit 0X27
Sequence d'Init LCD 4x20 via I2C1 PCF8574
.123456789A
Affichage sur LCD 4x20
Chargement caracteres Speciaux set #1 en
CGRAM
Config et Init One Wire
TRAITEMENT demande
équalisation
Demande AUTO_etalonnage des 3 sondes DS18B20
elles doiveent etre reliees mecaniquement ensembles (meme
temperature ambiante)
Attente relache SW6 ..puis appui sur SW6>2sec
Logigramme :
Ordinogramme_Eqalisation_2023-0512.jpg
Chaudiere_Egalisation_DrawIO_2023-0512.pdf
Mesures T°AMB en fonction
de la position (Hauteur) de la sonde :
les 3 sondes au meme endroit, sur mon bureau :
.......sonde T2 Ext à 10cm au dessus du
sol
(16:35:46.829) T1.INTER.= 22.29° C
(16:35:46.829) T2.EXTER.=
20.48 °C
(16:35:46.829) T3.EAU = 22.04 °C
...................à 80cm du sol
(16:26:25.254) T1.INTER.= 22.23° C
(16:26:25.302)
T2.EXTER.= 21.98 °C
(16:26:25.302) T3.EAU = 22.04 °C
(16:26:26.563) 01599 Jeudi 27 Avril 23 16H26M31S
......
la sonde T2 Ext replacée à 200cm au
dessus du sol--> 22.92°C
(16:54:15.545) T1.INTER.= 22.42° C
(16:54:15.578) T2.EXTER.=
22.92 °C
(16:54:15.578) T3.EAU = 22.04 °C
(16:54:16.853) 02860 Jeudi 27 Avril 23 16H54M21S
on verifie ainsi , que l'air chaud monte !
...
ma station meteo indique 23.0°c
mon horloge numerique : 21.67°C
c'est peut etre pas utile d'aller chercher plus de
précision ! ..
Software :
main_3bus_3xDS18B20_11b_LCD4x20_IT_RB0_RTC_Tests_Equalisation_sondes_2023-0427.c
_18F27K42_3bus_3xDS18B20_11b_LCD4x20_IT_RB0_RTC_Tests_Equalisation_sondes_2023-0427.hex
_18F27K42_LCD_PCF8574_3bus_DS18B20_Int0_5BP_UART1_IT_Rx_RTC_2023-0427.zip
Horloge temps reel : RTC DS3231
.....avec
Environnement MPLABX et XC8
voir aussi http://paulfjujo.free.fr/_18F27K42_47K42/PIC18F27K42_Tests.htm#RTC
avec environnement
MikroC Pro 7.60
Rappel sur Hardware RTC
DS3231
usage
de la BASE PIC18F27K42
Utilisation de FOSC interne 64Mhz,
via config Bits
Liaison I2C1 sur RC3 et RC4, avec R pull up de 2,8K avec
RTC DS3231
Liaison UART sur RC6 (Tx) et RC7(Rx) avec Teraterm PC
application via cordon TTL/USB
Liaison ICSP avec Pickit 4 et MPLAB IPE V6.00 application
PC
une entree dédiée au Forcage de la date et Heure
schema:
Le programme démmare avec une reconnaissance des
devices connectés sur le Bus I2C1
si on a activé la compilation conditionelle !
#ifdef
With_Test_Presence_Devices
CPrint(" Test presence devices sur Bus I2C1\r\n");
Test_Presence_I2C_devices();
CRLF1();
#endif
les devices presents sont affichés sur le terminal avec
leur adresse I2C
dont la RTC en @ 0x68
Une premiere commande I2C permet de
démarrer l'horloge RTC et d'obtenir le cligotement
, à 1HZ,
sur la sortie SQWE de la RTC.. si
ça ne clignote pas = Problemo !
soit tmp[10] une table qui sera utilisée pour les
transfert datas I2C
* dans l'élément tmp[0] , on doit mettre la 1ere
adresse (registre) pointé dans le device connecté, ici
0x0E
* dans l'élement tmp[1], la valeur de la donnéee à
écrire, ici 0x40 (ou 0B0100000)
avec : #define DS3231_ADDR 0xD0 //0x68 I2C Hardware : sur
7 bits
//
set SQW output Start oscillateur
tmp[0]=0x40; // data
I2C1_Write1ByteRegister(DS3231_ADDR,0x0E, tmp[0]);
Pour Initialiser completement la RTC (neuve et
vierge) avec des valeurs plausibles,
on va pré-remplir les registres avec une date et heure
donnée.
soit la meme table tmp[10] utilisée pour les transfert
datas I2C
dans l'élément tmp[0] , on doit ECRIRE, mettre la 1ere
adresse (registre) pointé dans le device connecté
ici 0x00, adresse registre secondes
puis ecrire les datas dans les elements suivants
tmp[1]=valeur Sec
tmp[2]=valeur Mn
.. etc .
Cette toute premiere init peut etre forcée,
au lancement du programme,
via l'usage de la pin RB7 = 0 ( ou si l' ICSP est encore
connecté, au lancement du programme !)
sinon, on relit le contenu en cours de la RTC.(avec RB7=1)
CPrint(" Possibilité de
forçage init RTC inhibée pendant les tests\r\n");
for (i=1;i<32;i++) tmp[i]=0;
CPrint( " Etat pin RB7
= " );
if ( (PORTB & 0x80)==0x80) PrintChar('1'); else
PrintChar('0');
CRLF1();
if(RTC_Forcee==0) //
RB7 input
{
CPrint( " Init RTC Forcee a Lundi
17/04/2023 11:59:57 via RB7=0 \r\n");
tmp[0]=0x00; //start register
tmp[1]=0x57; //second
tmp[2]=0x59; //write min
tmp[3]=0x11; //write hour;
tmp[4]=0x01; ///write day of week
tmp[5]=0x17; // write date
tmp[6]=0x04; // write month
tmp[7]=0x23; // write year
tmp[8]=0x00;
SQA=1;
p1=&tmp[0];
I2C1_WriteNBytes(DS3231_ADDR,p1,8);
SQA=0;
}
else
{
__delay_ms(1000);
CPrint(" Simple re-Lecture et
affichage des 8 registres RTC DS3231 \r\n");
}
Une fois initialisée, la
RTC est autonome ( avec sa pile LIR2032 )
ATTENTION : utiliser
une CR2032 est risqué , Ubat=3,4V au lieu de 4,1V max pour LIR2032
Verification en
affichant le contenu de la RTC:
on va donc reLIRE
les registres RTC
et on affiche la date
complete ,jour de la semaine, jou,rmois,année, heures,minutes,
secondes
SOFTWARE :
MplabX XC8
rev: Compile le Apr 27 2023 a 20:06:37 UTC
Tables spécifiques pour RTC :
const char All_Jour_Semaine[]="ErLuMaMeJeVeSaDi";
char time[]="00H00M00S";
char date[]="00/00/00";
les fonctions sont dans la
librairie RTC_2023-04.h dont les
principales :
void Display_Date_Time(char Visu);
// relecture RTC et affichage( optionnel)sur Terminal et/ou
LCD, format HH:MM:SS
void Print_Date_Complete(void);
// date complete avec les noms des mois et jour de
semaine
void MAJ_RTC(void); //
procedure spéciale pour mise à jour via un terminal (ou
bluettooth) avec cette
commande specifique : "U;27;04;23;15;14;04;#"
pour le 27 avril 2023 15H14 Jeudi
mise à jour au changement d'horaire HIVER / ETE ou
eventuel remplacement de Pile
rappel des commandes via terminal : par envoi de "Help"
Nota : dans l'application
finale ,on prevoit un reglage Date et Heure via les BP et
le LCD .
ATTENTION : la RTC ne tient pas
compte du changement d'horaire ETE / HIVER => oblige
à faire une MAJ
RTC manuelle !
Issue de la SUB PROCEDURE TEST_ETE_HIVER()
en Basic de Gerard sur FANTAS-PIC !
adaptation en C (MPLAB XC8 et 18F27K42) :
Nota : cette fonction ne peut etre utilse que dans un
état STABLE et ACHEVé du programme, et sur du long
terme > 2 Ans
...et à condition qu'il n'y ait pas trop de coupure d'alim
.affaiblissant la pile 3,2V
Elle ne sera pas maintenue pour
cette application CHAUDIERE , vu la possibilité Manuelle
ou via l'UART ,de corriger l'heure RTC.
Flag à positionner :
#define
HIVER '1'
#define ETE '0'
// rev 23/09/2023
// rajout traitement heure ETE/HIVER
if ( ( mois==0x10) && (jour>0x24) && (jS==7)
&& (heure==0x03) && (minute==0x00)
&& (CH==ETE))
{
CH=HIVER ; // HIVER ='1'
heure=0x02;
I2C1_Write1ByteRegister(DS3231_ADDR,2,heure);//write
heure dans RTC
__delay_ms(25);
tmp[0]=HIVER; //
tmp[1]='H';
tmp[2]='I';
tmp[3]='V';
tmp[4]='E';
tmp[5]='R';
tmp[6]=0;
tmp[7]=0;
tmp[8]=0x00;
tmp[9]=0x00;
p1=&tmp[0];
for (i=0;i<8;i++)
{
DATAEE_WriteByte(0x000C+i,tmp[i]); // Eeprom du PIC18F
__delay_ms(50);
}
CPrint("Passage en Horaire d' ");Print(tmp+1);CRLF1();
}
if ( ( mois==0x03) && (jour>0x24) && (jS==7)
&& (heure==0x02) && (minute==0x00)
&& (CH==HIVER))
{
CH=ETE ; // ETE ='0 '
heure=0x03;
I2C1_Write1ByteRegister(DS3231_ADDR,2,heure);//write
heure dans RTC
__delay_ms(25);
// optionel !
tmp[0]=ETE; //
tmp[1]='E';
tmp[2]='T';
tmp[3]='E';
tmp[4]=' ';
tmp[5]=' ';
tmp[6]=0;
tmp[7]=0;
tmp[8]=0x00;
tmp[9]=0x00;
p1=&tmp[0];
for (i=0;i<8;i++)
{
DATAEE_WriteByte(0x000C+i,tmp[i]); // Eeprom du PIC18F
__delay_ms(50);
}
CPrint("Passage en Horaire d' ");Print(tmp+1);CRLF1();
}
sur RESET , relecture du flag
CPrint(" Horaire d' ");
CH=DATAEE_ReadByte(0x000C);
__delay_ms(25);
for (i=0;i<7;i++)
{
cx=DATAEE_ReadByte(0x000C+i);
if (i==0) CH=cx; else PrintChar(cx);
__delay_ms(25);
}
extraits affichage sur terminal
00043 Dimanche 31/03/24
01H59M59S
00044 Dimanche 31/03/24 02H00M02S
00045 Passage en Horaire d' ETE
Dimanche 31/03/24 03H00M05S
00046 Dimanche 31/03/24 03H00M07S
00047 Dimanche 31/03/24 03H00M10S
00048 Dimanche 31/03/24 03H00M12S
reset
....
Re-Lecture et affichage des 8
registres RTC DS3231
Temperature DS3231 => 26.25°C
Horaire d' ETE
adresse LCD= 32 soit 0X20
....
00015
BAV=2
Recu :BAV=2
00016 Dimanche 31/03/24 03H02M15S
00017 Dimanche 31/03/24 03H02M18S
00018 Dimanche 31/03/24 03H02M20S
00059 Dimanche 31/03/24 03H03M58S
00060 Dimanche 31/03/24 03H04M01S
U;23;09;23;11;26;06;#
Recu :U;23;09;23;11;26;06;#
MAJ RTC
U;23;09;23;11;26;06;#
Ecriture DS3231... OK
00061 Samedi 23/09/23 11H26M00S
00062 Samedi 23/09/23 11H26M02S
00063 Samedi 23/09/23 11H26M04S
00485 Dimanche 31/10/23
02H59M52S
00486 Dimanche 31/10/23 02H59M55S
00487 Dimanche 31/10/23 02H59M57S
00488 Dimanche 31/10/23 03H00M00S
00489 Passage en Horaire d' HIVER
Dimanche 31/10/23 02H00M02S
00490 Dimanche 31/10/23 02H00M05S
00491 Dimanche 31/10/23 02H00M07S
SOFTWARE :
la partie de code correspondante :
MAJ-RTC_via_Asccii_LCD_2023-0918.X.c
MAJ RTC via terminal (ou appli
Android) :
La plus simple !
il suffit de préparer coté terminal YAT le texte
suivant le format suivant ;
U;27;04;23;15;14;04;#
pour le 27 avril 2023 15H14 Jeudi
entete = U;
separateur = ;
suffixe =#
voir : Dialogue_Operateur_PC_via_UART_2023-0905.inc
résumé ci dessous
p0 pointe sur le Buffer de reception UART1
if ( (*(p0)=='U') && (*(p0+1)==';') && (
*(p0+19)==';') && (HHMN_force==0 ))
{
CPrint("\r\n MAJ RTC \r\n");
Print(Buffer1); CRLF1();
MAJ_RTC();
CRLF1();
p0=0;
}
MAJ AUTOMATIQUE RTC (
autre possibilité)
via la compilation MPLAB XC8,
recuperation Date et Heure du PC
voir aussi sur FANTASPIC
https://fantaspic.fr/viewtopic.php?f=10&p=20284#p20284
recup Datas PC System via les variables de directives de
compilation MPLAB
__DATA__ et __TIME__
Oct 15 2023
11:56:43
pour initialiser la RTC ..
ATTENTION aux
valeurs pouvant representer de l'ASCII, BINAIRE, ou BCD
...
La RTC nécessite du BCD !
Le numéro du jour dans la semaine n'est pas transmis par
MPLAB
Recherche de ce jour via le calcul du Jour Julien
fonction ( an,mois,jour)
pour determiner ce jour de semaine
qui sera assigné à jS parametre #04 de la RTC
on peut donc ainsi initialiser completement la RTC
// ----date et RTC -----
long Jour_Julien;
const char Prefixe_Mois[12][4]={
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
const char Jour0[]="Lundi ";
const char Jour1[]="Mardi ";
const char Jour2[]="Mercredi ";
const char Jour3[]="Jeudi ";
const char Jour4[]="Vendredi ";
const char Jour5[]="Samedi ";
const char Jour6[]="Dimanche ";
const char Jour7[]="Error ";
const char * JourSemaine[]={Jour0,Jour1,Jour2,Jour3,Jour4,Jour5,Jour6,Jour7};
long jour2jul(char jour
, char mois , int annee)
{
long jule, gregorien, a , j , m;
/* Attention, cette routine ne doit etre appellee que si
on est sur
que le jour fourni en param?tre existe !!!!!! */
a = (long)annee;
m = (long)mois;
j = (long)jour;
// On commence par faire un ajustement pour les annnees
negatives
if (annee < 0) a++;
jule = ((489L *m - 481 ) >>4) + j + 1721423L - (((a&3)+7)>>2)*((m+13)>>4)
+ ((1461L*(a-1))>>2);
/* Avant le 04/10/1582 on est en calendrier julien, et en
calendrier gregorien apres le 15/10/1582 */
if (jule <= 2299160L)
return jule;
/* En calendrier gregorien les ajustements ? faire sont :
- les annees divisibles par 100 ne sont pas bissextiles
- les annees divisibles par 400 sont bissextiles.
*/
gregorien = jule - (a/100L - a/400L - 2L);
if ( ( (a%100) == 0 ) && (m < 3) && (
(a%400) != 0)) gregorien++;
return gregorien;
}
char *j_txt(long n ,
char *num)
{
char c;
if (n < 0L)
c = 6 - (char)((-n-1)%7);
else
c = (char)(n%7);
*num = c;
return (char *)JourSemaine[c];
}
Le seul bémol est que le
TIME MPLABX est en retard de la duree de compilation
estimée ici à 1mn 20" ( puis 49sec pour les
compilations suivantes sans modif de code !)
ce n'est donc pas le Perrou !
... mais on peut toujours rajouter 1' 20" au temps (
ou 49sec)
L'autre probleme est le flag automatique ETE / HIVER qui
depend du moment de compilation
car sauvé en EEPROM et relu ensuite ..
cela implique de garder :
- une possibilite MANUELLE de rectifier le contenu RTC (
dialogue via BP et LCD)
- ou via la liasson UART (dialogue Operateur) en envoyant
la sequence d'inite sous la forme :
U;15;10;23;14;20;06;# pour 15 octobre 2023 , 14H20,
Dimanche \r\n")
Test jour Julien
date 29/08/1996 -> jour julien # 2450325 Jeudi jour #
3
date aujourd'hui 15/10/2023 -> jour julien # 2460233
Dimanche jour # 6
#ifdef INIT_AUTO_RTC
CPrint("\r\n Datas PC System \r\n");
sprintf(txt,"%s", __DATE__); // Oct 14 2023 11
cars
Print(txt);CRLF1();
sprintf(CRam1,"%s", __TIME__);
Print(CRam1);CRLF1(); //15:02:12 8 cars
CRLF1();
CPrint(" recup datas (en BCD !!) pour init RTC \r\n");
// decodage pour le Numero du mois
*(txt+3)=0; CPrint("Mois = ");Print(txt);
i=0;
do
{
if (strcmp( &Prefixe_Mois[i],txt) ==0 )
{
sprintf(Tampon,"..mois trouve =%d ",i+1);
Print(Tampon);
CRLF1();
mois=Dec2Bcd(i+1);
break;
}
i++;
}
while (i<12);
*(txt+6)=0; CPrint(", jour = ");Print(txt+4);
jour=(*(txt+4)-48)*16 + *(txt+5)-48; // jour=atoi(txt+4);
*(txt+11)=0;
CPrint(", Annee = ");Print(txt+9);
Annee=(*(txt+9)-48) *16 + *(txt+10)-48; //Annee=atoi(txt+9);
CRLF1();
* (CRam1+2)=0;* (CRam1+5)=0;* (CRam1+8)=0;
heure= (*(CRam1)-48 ) *16 + *(CRam1+1)-48; // en BCD !!
minute=(*(CRam1+3)-48) *16 + *(CRam1+4)-48;
second=(*(CRam1+6)-48) *16 + *(CRam1+7)-48;
sprintf(txt,"JMA= %02x/%02x/%02x , time %02x:%02x:%02x\r\n",jour,mois,Annee,heure,minute,second);
Print(txt);
CRLF1();
CPrint(" Test jour Julien\r\n");
Jour_Julien=jour2jul(29,8,1996);
sprintf(txt," date 29/08/1996 -> jour julien # %ld",Jour_Julien);
Print(txt);PrintChar(TAB);
// jour de la semaine
Print(j_txt(Jour_Julien , &cx));
CPrint(" jour # ");PrintChar(cx);
PrintChar(cx+48);
CRLF1();
i=Bcd2Dec(jour);
j=Bcd2Dec(mois);
k=Bcd2Dec(Annee);
Jour_Julien=jour2jul(i,j,k+2000);
sprintf(txt," date aujourd'hui 15/10/2023 -> jour
julien # %ld",Jour_Julien);
Print(txt);PrintChar(TAB);
// jour de la semaine
Print(j_txt(Jour_Julien , &jS));
CPrint(" jour # ");
PrintChar(jS+48); CRLF1();
CRLF1();
CPrint(" MAJ RTC !\r\n");
// avec datas en BCD !
tmp[0]=0x00; //stop Oscillateur
tmp[1]=second; ;
tmp[2]= minute;
tmp[3]= heure;
tmp[4]=jS; //write day of week
tmp[5]=jour;
tmp[6]=mois;
tmp[7]=Annee;
tmp[8]=0;
p1=&tmp[0];
I2C1_WriteNBytes(DS3231_ADDR,p1,9);
#endif
Cette fonctionalité,
interessante , ne sera pas retenue pour
l'application "Chaudiere"
( car modif Manuelle possible, via BP& LCD, ou via
Terminal UART)
Test
interruptions INT0 RB0 sur changement d'etat des entrées
PORTB
avec le même schéma
, sur montage prototype Breadboard
Suite au test BP Switches 0 à 5 en mode pooling, cette
fois on utilise l'interruption INT0 sur pin RB0
qui regroupe tous les switches via un circuit OU à
diodes
il suffit d'un seul switch à 0 , pour déclencher l'interrupt
sur Front Descendant de RB0.
Le registre interne IOCB regroupe l'etat des
entrées PORTB au moment de l'interrupt.
On peut donc avoir plusieurs BP (switches) actionnés en
meme temps, si on lit l'etat des flags IOCBF apres un
cours lapt de temps
pour eviter la fausse lecture de rebonds de contact
mecanique ( toujours presents
!!)
La grosse difference est la
réactivité immediate ,SANS SURVEILLER en
permanence l'état des 6 BP. (comme dans le mode pooling)
Choix du front descendant (car les 6 BP ont des R pull-up
au +VCC , donc niveau 1 (sur tous les BP,au repos )
dans la configuration hardware
ANSELB = 0x00; // aucune pin en
analogique
TRISB = 0xFF; // toute sles pins en entrées
WPUB = 0xFF; // pull up interne activée
// pas d'affection aux peripheriques MCU
RB0PPS=0;
RB1PPS=0;
RB2PPS=0;
RB3PPS=0;
RB4PPS=0;
RB5PPS=0;
RB6PPS=0;
RB7PPS=0;
ODCONB = 0x00;// pas d'open collecteur
SLRCONB = 0x80; //0xFF; // pas de limite de vitesse
IOCBF=0; // RAZ Flag etat port B
IOCBN=0; //
pas de detection front descendant
IOCBP=0; // pas de detection front montant
dans vecteurs d'interruptions :
Interrupt_Init(); // IPR1bits.INT0IP
= 1; // mode haute priorité
Le
Traitement de l'interruption
void __interrupt(irq(IRQ_INT0),high_priority)
INT0_ISR(void)
{
//INT0IF: External Interrupt 0 Interrupt Flag bit
// The external interrupt GPIO pin is selected by the
INTxPPS register.
if ( ( PIR1bits.INT0IF
==1) && ( PIE1bits.INT0IE==1))
{
U1TXB='*';
// bref message sur terminal
Drapeaux.Key_ON=1;
__delay_ms(60); // delay anti rebonds contact
sec, indispensable !
// chrono duree appui avec compteur timer 24 bits SMT1
SMT1STATbits.RST=1;
SMT1CON1bits.SMT1GO=1; //
start chronometre
// REGISTER 18-3: IOCxF: INTERRUPT-ON-CHANGE FLAG
REGISTER
// channgement d'etat sur pins :
Etats_IOCBF=IOCBF
& 0x3E; // actuelle sauf RB5 (non cablé!) sinon 0x7E
// RB7 et RB6 sur ICSP !.... pas de SW5 cablé
Etats_BP = Etats_IOCBF >>1 ; // on recentre les bits à
droite => SW0 bit 0 ... SW5 bit 5
__delay_ms(20); // delay minimum de lecture etat appui
// les
aigillages pour le choix des menus est fait ICI
// mais les
traitements des Menus se feront dans le main (boucle
principale du programme)
switch (Etats_BP)
{
case 1 : // SW0
&enspMenu=10;
&enspPIE1bits.INT0IE=0; // la
suite en mode pooling
break;
case 2 :
&enspMenu=1;break; // SW1 mode Cf
ou EC
case 4 :
&enspMenu=2;break; // SW2 incr
consigne
case 8 :
&enspMenu=3;break; // SW3 dec
consigne
case 6 :
&enspMenu=5;break; // SW1+SW2
bascule consigne Hors gel ou Normal
case 10 :
&enspMenu=6;break; // SW1+SW3
case 16:
&enspMenu=4; // SW4
&enspbreak;
case 32:
&enspMenu=7; // SW5
&enspbreak;
default:
&enspEtats_BP=0;
&enspbreak;
}
// attente relache BP;
while( (PORTB & 0x3E) != 0x3E);
SMT1CON1bits.SMT1GO=0; // ici on arrete le chronometre
ST=&SMT1_Measure;
*(ST)=SMT1TMRL;
*(ST+1)=SMT1TMRH;
*(ST+2)=SMT1TMRU;
*(ST+3)=0;
U1TXB='#';
Duree_Appui=SMT1_Measure/500; // Nbde ticks de 2µ donc
multiplie *2 et div par1000 pour mS
// IOCBF=0;
PIR1bits.INT0IF =0;
Count_RB0++;
cx=PORTB;
IOCBF=0;
}
}
puis, ensuite, apres les differentes initialisations
dans le main programme
#define VERSION "2023-0430"
#define With_SMT1
//#define With_Tests_SMT1
PIE0bits.IOCIE=0;
IOCEN=0;// invalide toutes interrup IOC
PIR0bits.IOCIF=0;
IOCBP=0; //pas de detection front Montant sur PORTB
IOCBN=0b01111111; //detection front descendant (Negatif)
sauf RB7
IOCBF=0; // RAZ flag etat pins IOC PORTB
Drapeaux.Key_ON=0; // raz flag detection interrupt INT0
PIR1bits.INT0IF=0; // RAZ flag detection interrupt INT0
PIE1bits.INT0IE=1; // autorisee
interrupt INT0 sur front descendant pin RB0
GIE=1; // autorise Toutes les interruptions
( + dont l'UART RX !)
Apres plusieurs test avec des Timers ( TMR4,TMR0,TMR1),
il s'avère que l'usage de SMT1 compteur 24bits
avec une resolution de +-2µS ou +-1mS (au choix) est
tres ouple : Large dynamique de mesure ( avec 24bits au
lieu de 16)
Test des 6 B.P. (sur carte PCB ) , avec usage Interrupt IVT INT0 (sur RB0)
et reconnaissance du BP appuyé via l'etat de IOCBF (byte)
regroupant l'entre(s) ayant eu un front descendant
rev 23/08/2023 ,
Ctte fois , avec les Boutons POussoirs montés
sur la carte PCB !
sans les aleas de
mauvais contacts en version Breadboard !
SW0 à SW5 sur respectivement RB1 à RB6
et OU logique resultant sur RB0,
chaque appui de BP genere un front descendant sur RB0 =>
INT0
IOCBF memorise quel sont les fronts descendants
détectés.
la duree est mesurée par un simple boucle d'attente
relachement BP ( qui tourne sur un delay de 100µS)
et aussi usage de SMT1 pour cette mesure de durée ..il s'avere
que l'usage de SMT1 est trop "Luxueux " ici
et sera donc supprimé par la suite.
voir : void __interrupt(irq(IRQ_INT0),high_priority)
INT0_ISR(void) dans le programme
Nota : un appui > à 5sec elimine l'evenement , aucun
BP prise en compte..
resultat sur YAT terminal.
Test des 6 BP unitaires ou combinés ...
Software:
18F27K42_test_INT0_IOCBF_6BP_Uart1_AVEC_IVT_2023-08.zip
main_test_INT0_IOCBF_6BP_AVEC_IVT_2023-0823.c
18F27K42_test_INT0_IOCBF_6BP_Uart1_2023-0821.X.hex
Liaison BlueTooth Carte Chaudiere
<--> Terminal PC YAT
HARDWARE :
![]() |
![]() |
convertisseur TTL/USB CH340G |
HC05 Maitre ou Esclave |
info Converter
:
USB Device Tree Viewer :
Service : CH341SER_A64
Device Bus Speed : 0x01 (Full-Speed)
bcdUSB : 0x110 (USB Version 1.10)
------------------ Device Descriptor ------------------
Length : 0x12 (18 bytes)
DescriptorType : 0x01 (Device Descriptor)
cdUSB : 0x110 (USB Version 1.10)
DeviceClass : 0xFF (Vendor Specific)
DeviceSubClass : 0x00
DeviceProtocol : 0x00
MaxPacketSize0 : 0x08 (8 bytes)
idVendor : 0x1A86
idProduct : 0x7523
bcdDevice : 0x264
iManufacturer : 0x00
iProduct : 0x02
Language 0x0409 : "USB Serial"
iSerialNumber : 0x00
NumConfigurations : 0x01
info via USBVIEWER :
firmware:2.64
vendeur:QinHeng Electronics
service: CH341SER_A64
fabricant : wch.cn
Alim: 98mA
version USB 1.10 01/08/2023 17:50:43
BlueTooth Device :
Liaisons converter <---> HC05
0V --------------- 0V
+5V USB --------+VCC
TX ----R 1K------RX et RX ---- 2,7K ----0V
RX ---------------TX
Le HC05 ESCLAVE coté carte chaudiere en mode SSP
Protocole serie = liaison série transparente
=> pas de configuration à faire..
(vrai) Module HC05 monté sur Carte CHAUDIERE
verifications:
AT+VERSION.....................VERSION:3.0-20170601
AT+ADDR? ........................+ADDR:98D3:21:F7FE7B
AT+NAME? .......................+NAME:HC05_FE7B
AT+UART? .........................+UART:115200,0,0
AT+ROLE ............................+ROLE:0....mais
utilisé ici en mode ESCLAVE
Le HC05 sur mini
breadboard,
référencé ici comme HC05-8E51 ( car adresse MAC se
terminant par 8E51)
doit etre MAITRE coté PC,
=> Il faut d'abord configurer le HC05 en mode maitre (
sinon, en esclave par defaut)
...passer en mode commande AT
..il faut maintenir le Bouton poussoir sur le HC05
appuyé pendant la prise de contact dialogue
Le terminal YAT est à 9600bds ( vitesse par defaut d'un
HC05 neuf)
AT
OK
AT+VERSION
VERSION:3.0-20170601
OK
AT+ROLE
+ROLE:0 ................. <-
Esclave
OK
AT+UART?
+UART:9600,0,0
OK
AT+ADDR?
+ADDR:21:13:8E51
OK
AT+NAME?
+NAME:HC-05
OK
AT+STATE?
+STATE:PAIRABLE
OK
------------------------------
changement de vitesse HC05
-----------------------------
AT
OK
AT+UART=115200,0,0 ............... modif Vitesse à 115200 bds
OK
---Il faut aussi changer la
vitesse sur le terminal !--------
AT
OK
AT+ROLE=1 ................
maintenant en mode MAITRE
OK
des qu'il est en maitre il va
essayer de se connecter sur un device bluetooth
environnant..
AT
OK
ou via une commande explicite de
recherche
AT+INQ........................................................
detecte les devices bluetooth autour de lui
+INQ:15:83:2B6D87,104,FFD3
+INQ:15:83:2B6D87,104,FFD2
+INQ:98D3:21:F7FE7B,1F00,FFD1
+INQ:15:83:2B6D87,104,FFD5
+INQ:15:83:2B6D87,104,FFCC
+INQ:98D3:21:F7FE7B,1F00,FFD2
+INQ:98D3:21:F7FE7B,1F00,FFD1
+INQ:98D3:21:F7FE7B,1F00,FFD0
+INQ:98D3:21:F48701,1F00,FFAB
+INQ:15:83:2B6D87,104,FFD4
+INQ:15:83:2B6D87,104,FFD3
+INQ:15:83:2B6D87,104,FFD5
+INQ:15:83:2B6D87,104,FFCB
+INQ:15:83:2B6D87,104,FFD2
+INQ:15:83:2B6D87,104,FFCA
+INQ:15:83:2B6D87,104,FFD2
+INQ:15:83:2B6D87,104,FFC1
+INQ:15:83:2B6D87,104,FFD4
AT+BIND=98D3;21,F7FE7B................. <-----
Association, Liaison bluetooth choisie
OK
+INQ:15:83:2B6D87,104,FFD2
+INQ:15:83:2B6D87,104,FFD4
Cpt= 20 ;Sam;26/08/23;16:02:26; 28.62¦C ...........<---ça c'est mon horloge
numerique
00310 .................................<--connecté
maintenant sur datas CHAUDIERE !!!
00311
...
00360
00361
# 00362
Duree = 977 mS , BP=0X22, Menu= 0
00363
00364
# 00365
Duree = 1473 mS , BP=0X02, Menu= 1 SW1
SW1 Toogle Change Mode CONFORT / ECO
mode : Ec et Mode_Forc desactive
00366
# 00367
Duree = 1417 mS , BP=0X04, Menu= 2 SW2
Etats_BP= 00 SW2 Incr consigne frcee ECO : 15.50
00368
# 00369
Duree = 1350 mS , BP=0X04, Menu= 2 SW2
Etats_BP= 00 SW2 Incr consigne frcee ECO : 16.00
00370
....
00392
------------------------------------------------------------------------
mise hors tension HC05 par deconnection USB coté PC
-----------------------------------------------------------------------
reconnection
automatique sur Chaudiere !
00402
00403
00404
00405
--------------------------------------------------------
re-verif parametres (en appuyant sur le B.P. HC05)
------------------------------------------------------
AT
OK
AT+STATE?
+STATE:CONNECTED
OK
AT+MRAD? ......................................derniere
adresse connectée
+MRAD:98D3:21:F7FE7B................adresse MAC du HC05 esclave
carte Chaudiere
OK
AT+ADDR?
+ADDR:21:13:8E51
OK
AT+ROLE
+ROLE:1
OK
reconnection
automatique sur Chaudiere !
00416
00417
Nota :
avec ce montage PONT de connexion
je peux me connecter aussi à mes 3 horloges numeriques
et à mon appli EDF Info ..
sans avoir besoin de l' application BlueSoleil , tournant
en tache de fond sur le PC.
Autres détails sur ce lien :
18F_BlueTooth.htm
Test stockage et
restitution valeur flottante en Eeprom PIC
Fonctions incluses dans
Eeprom_PIC_2023.c
float Read_Float_from_Eeprom(unsigned
int Adresse)
{ int j;
unsigned char *Pt;
float Rf;
Pt=&Rf;
for (j=0;j<4;j++) *(Pt+j)=DATAEE_ReadByte(Adresse+j);
return Rf;
}
------------------------------
void Sauve_Float_To_Eeprom(unsigned int
ad1,float Fv)
{ unsigned int i;
static unsigned char *pt;
GIEH=0;
pt=&Fv;
for (i=0;i<4;i++)
{
DATAEE_WriteByte(ad1+i,*(pt+i));
__delay_ms(25); // important !
}
GIEH=1;
}
-------------------------------------
#ifdef Test_sauve_restitue_Eeeprom
#ifdef Test_sauve_restitue_Eeeprom
Txcor[0]=0.5678;
Txcor[1]=1.2345;
Txcor[2]=-0.987;
sprintf(txt," Txcor[0]= %5.3f \r\n Txcor[1]= %5.3f\r\n
Txcor[2]= %5.3f\r\n",Txcor[0],Txcor[1],Txcor[2]);
Print(txt);
CPrint(" Sauve corrections capteurs DS18B20 ->
eeprom PIC .. OK\r\n");
Sauve_Float_To_Eeprom(Org_Txcor,Txcor[0]);
Sauve_Float_To_Eeprom(Org_Txcor+4,Txcor[1]);
Sauve_Float_To_Eeprom(Org_Txcor+8,Txcor[2]);
CPrint(" Restitue corrections capteurs DS18B20 <---
depuis Eeprom PIC\r\n");
Txcor[0]= Read_Float_from_Eeprom(Org_Txcor);
Txcor[1]= Read_Float_from_Eeprom(Org_Txcor+4);
Txcor[2]= Read_Float_from_Eeprom(Org_Txcor+8);
sprintf(txt," Corrections restituees \r\n Txcor[0]=
%5.3f \r\n Txcor[1]= %5.3f\r\n Txcor[2]= %5.3f\r\n",Txcor[0],Txcor[1],Txcor[2]);
Print(txt);
CRLF1();
while(1);
#endif
Results :
Test PIC Eeprom :
Ecr/lec des parametres et ensemble de 10 programmes
horaires
Organisation Eeeprom
voir Tables_Programmation_et_eeprom_PIC_2023-0515.xls
Une table de travail contenant les 10 programmes horaires
est définie en RAM .
Elle est initialisée en dur , dans le code .
Au 1er Lancement de l'application, un test est fait sur
un Flag (dénommé "Run_Once") qui est le 1er
byte de l'eeprom ( adress 0x0000)
si il ne contient pas 99, ( 0xFF si eeprom vierge), le
contenu de la table de travail est recopié en Eeprom à
partir
de l'adresse.... #define
Org_Tables_Prg_Horaire 0x100
les differentes adresses Eeprom sont regroupées dans
le fichier Define_Org.h
et le Flag "Run_Once" adresse 0x0000 est
mis à 99 .
de ce fait, cette operation ne sera executée qu'une
seule fois !
Exemple de lecture : Tables horaires en Eeprom
affichage que de la partie utile 25 bytes / 32
Lecture
table programmes horaire en eeprom
Relecture datas eeprom :
Flag Run Once at @ 0x0000 =99
Programme version : 230511
0x0100
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, Progr= C
0x0120
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, Progr= E
0x0140
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00, Progr= D
0x0160
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00, Progr= M
0x0180
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
0x03, 0x03,
0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00, Progr= R
0x01A0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
0x00, 0x00, Progr= A
0x01C0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00, Progr= J
0x01E0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00, Progr= P
0x0200
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x03, 0x03, 0x03,
0x01, 0x00, Progr= T
0x0220
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, Progr= V
La table de 10 programmes horaires a une taille globale
de 10x32 bytes dont 24 sont utilisés pour cela
le 25em byte contient un caractere definissant le nom du
programme .. et 7 bytes inutilisés
Pourquoi 32 ?:
pour garder une granulometrie modulo 32 bytes .. car plus
facile à gérer quand on est modulo 8 ( ou 32!)
A chaque modif de programmation horaire , dùment
validée,
le programme visé sera sauvegardé en Eeprom PIC
Les corrections de temperatures seront sauvegardées (en
format flottant =4 bytes)
à partir de #define Org_Txcor
0x0030
donc 3x4 =12 bytes
Sur Reset ou sur coupure d'alim,
toutes les données Tables Horaires et corrections
de temperatures
seront remontées de l'Eeprom => Ram de travail.
via les fonctions définies dans :
Eeprom_PIC_2023.h
void
DATAEE_WriteByte(int bAdd, unsigned char bData);
unsigned char DATAEE_ReadByte(int bAdd);
void Sauve_Float_To_Eeprom(unsigned int ad1,float Fv);
float Read_Float_from_Eeprom(unsigned int Adresse) ;
void Lecture_Eeprom_Table_Programmes_Horaires(char Visu);
void Restitue__Corrections_Temper(void);
void Sauve_Corrections_Temper(void);
ATTENTION #1 !
si dans le Linker "Initialise Data" n'est pas
coché
L'init dans le code des tables Horaire (qui sont en RAM)
ne se fait pas !
C'est surtout problematique au 1er lancement du programme
!
ATTENTION #2 !
Production
....Set project configuration
........customise
...........selectionner Picki4
..............Memories to program
................Manually to select memories and ranges
il faut activer Preserver EEPROM Memory pour
que le Pickit4 n'efface pas celle-ci
MAIS laisser la case EEPROM cochée !
Dans ce cas là , MPLAB relit le contenu de l'eeprom et
le remet ensuite apres le chargement du *.hex
SOFTWARE :
Sauvegarde des parametres (
voir fichier xls au dessus!)
void Sauve_Parametres_en_Eeprom(unsigned
int Where)
{
int i;
if ((Where==Org_Sauve_Param_Travail) || (Where==Org_Sauve_Param_Usine))
{
if (Bavard==1)
{
sprintf(CRam1," \r\n Sauve Parametres en %4X \r\n",Where);
Print(CRam1);
}
Sauve_Float_To_Eeprom( Where+ 0 , EAU_min );
Sauve_Float_To_Eeprom( Where+ 4 , EAU_max );
Sauve_Float_To_Eeprom( Where+ 8 , EXT_min );
Sauve_Float_To_Eeprom( Where+ 12 , INT_cor );
Sauve_Float_To_Eeprom( Where+ 16 , INT_csg );
Sauve_Float_To_Eeprom( Where+ 20 , CFR_csg );
Sauve_Float_To_Eeprom( Where+ 24 , ECO_csg );
Sauve_Float_To_Eeprom( Where+ 28 , HGL_lim );
Sauve_Float_To_Eeprom( Where+ 32 , HYS_int );
Sauve_Float_To_Eeprom( Where+ 36 , HYS_ext );
Sauve_Float_To_Eeprom( Where+ 40 , HYS_eau );
DATAEE_WriteByte ( Where+ 44, Progr_En_Cours);
// dummy alignement pair ..45 not used
//rappel :Affectation_Hebdo[[]={'C','C','C','C','C','C','C',0};
for (i=0;i<8;i++) DATAEE_WriteByte (Where+ 46+i,Affectation_Hebdo[i]);
}
else
{
if(Bavard==1) CPrint(" \r\n Erreur adresse Eeprom
pour Parametres \r\n");
}
}
Le contenu de l'eeprom PIC peut etre lu , via MPLABX IDE
:
sous MPLABX IDE
. windows
.. target memory vues
..... EE data memeory
.......... read EE data memory to file => EE_memory_2023-0515.hex
avec Tables_Programmation_et_eeprom_PIC_2023-0515.xls
copier coller le contenu de EE_memory_2023-0515.hex
dans l'onglet Contenu eeprom PIC, à partir de la case B8
excel redécompose le contenu .des differentes zones..
à remarquer le doublon de la partie Eeprom TRAVAI , dans
la Partie EEPROM USINE
au tout premier lancement de programme seulement
.. par la suite, la possibilitéde de reinitialiser le
tout avec Parametres et Tables horaire USINE , est
prévue!
Attention : une remontée des Datas USINE necessite de
refaire les corrections EGALISATION températures des 3
sondes DS18B20
car celles ci sont remises à zero.
Integration
du Compteur SMT1
Le SMT1 a 3 registres 8 bits pour former ce compteur 24bits.
Declaration d'un entier long non signé de 32 bits (4
bytes) pour contenir cette valeur... le MSB sera donc
toujours à 0
Declaration d'un pointeur sur cette valeur pour le
transfert des registres SMT1... le MSB sera donc toujours
à 0
unsigned long SMT1_Measure;
unsigned char *ST;
unsigned long L1=0;
unsigned long L2=0;
Init du SMT1
il faut choisir un mode parmi 16 : ici mode Timer
= 0000 ( pas de lien (Pins) avec le monde
exterieur)
L'horloge clock de ce timer
Plusieur possibilité via 3 registres; SMT1CLKbits.CSEL2,
CSEL1,CSEL0
Usage d'un parametre passé à la fonction ,permettant de
chosir cette référence de comptage
if (Choix_SMT1_Clock<6)SMT1CLKbits.CSEL=Choix_SMT1_Clock;
avec Choix_SMT1_Clock =>// 0=FOSC/4, 1=FOSC , 2=HINTOSC
16MHz , 4= MFINTOSC (500 kHz ) ,5=MFINTOSC/16 (31.25kHz)
Dans cette application : choix =4 =>
tick resolution +-2µS
La mesure finale sera multiplié par 2, si on veut
afficher des µSec
ou divisée par 500 ( *2 et /1000) si on veut des mSec
exemple d'usage :
dans le main program:
CPrint(" Init Compteur 24 bits SMT1, avec choix
clock 4=> 500KHz tick=2µS\r\n");
// 0=FOSC/4 1=FOSC 2=HINTOSC 16MHz 4= MFINTOSC (500 kHz )
5=MFINTOSC/16 (31.25kHz)
SMT1_Init(4);
SMT1_Measure=0;
ST=&SMT1_Measure;
// pointeur positionné
SMT1STATbits.RST=1;
// reset ancienne valeur
SMT1CON1bits.SMT1GO=1;
__delay_ms(5);
SMT1CON1bits.SMT1GO=0;
// recup. contenu
du compteur 24bits
*(ST)=SMT1TMRL;
*(ST+1)=SMT1TMRH;
*(ST+2)=SMT1TMRU;
*(ST+3)=0;
L1=SMT1_Measure; //
mesure brute
L2=L1<<1; // à 500Khz tick=2µS => multiplie
par 2
// L2=L1/500; // resultat en mS ... multiplie par 2 et /1000
sprintf(txt,"\r\n Test SMT1 sur
delay 5mS , Nb Tics %lu L2=%lu uS\r\n",L1,L2);
Print(txt);
Tests avec SMT1 sur terminal :
ATTENTION au PB avec sprintf : %u
pour 16bits et ou %lu pour 32 bits !
Init Compteur 24 bits SMT1, avec choix clock 4=> 500KHz
tick=2µS
Test SMT1 sur delay 5mS , Nb Tics 2498 L2=4996 us
Test delay 50mS SMT1_Measure 24998 et L2 49996 uS
Test delay 500ms SMT1 = 249998 L2= 499 mS
Test delay 1500ms SMT1 = 749997 L2= 1499 mS
Test delay 10sec SMT1 = 5000005 L2= 10000 mS
On a donc maintenant , via ce chronometre SMT1, la mesure
de durée d'appui sur un BP
exemple de test dans la boucle
principale :
const char Switches[6][6]={"
SW0 "," SW1 "," SW2 "," SW3
"," SW4 "," SW5 "};
txt=&TEXTE[0];
// si on a
memorisé un changement d'etat sur un (ou des) BP
if(Etats_IOCBF>0)
{
sprintf(txt," Duree = %d mS
, ",Duree_Appui);
Print(txt);
// CRLF1();
sprintf(txt," BP=%02X, IOCBF= %02X
Menu=%3d ",Etats_BP,Etats_IOCBF,Menu);
Print(txt);
// on
récupere le Nom du BP !
for (i=0;i<6;i++)
{ cx=1<<i;
// nom du
switch affiché aussi sur LCD
if (Etats_BP==cx )
{
CPrint(Switches[i]);
LCD_Write_CText_At(4,1,"Etat ON sur
");
LCD_Write_CText_At(4,12,Switches[i]);
}
}
Etats_IOCBF=0;
Drapeaux.Key_ON=0;
CRLF1();
}
else
{ // pas de
BP appuyé
LCD_Write_CText_At(4,1,"Etats OFF
sur Switch");
CPrint("No switch ON\r\n");
}
Resultats sur YAT Terminal :
No switch ON
*#*# 00045 Dimanche 30 Avril 23 14H56M59S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
Duree = 19 mS , BP=02,
IOCBF= 04 Menu= 1 SW1
00046 Dimanche 30 Avril 23 14H57M00S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
No switch ON
*#*# 00047 Dimanche 30 Avril 23 14H57M01S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
Duree = 19 mS , BP=04,
IOCBF= 08 Menu= 2 SW2
*#*# 00048 Dimanche 30 Avril 23 14H57M03S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
Duree = 19 mS , BP=08,
IOCBF= 10 Menu= 3 SW3
*#*# 00049 Dimanche 30 Avril 23 14H57M05S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
Duree = 20 mS , BP=10,
IOCBF= 20 Menu= 4 SW4
*# 00050 Dimanche 30 Avril 23 14H57M06S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
Duree = 263 mS , BP=01,
IOCBF= 02 Menu= 10 SW0
SW0 Phase= 10 Pas=0
00051 Dimanche 30 Avril 23 14H57M07S
T1.INTER.= 20.37° C
T2.EXTER.= 21.06 °C
T3.EAU = 20.50 °C
nota : avec SW0 ,on n'a plus d'interruption BP
car on travaille dans le plus important Menu ..en restant
en mode pooling
On revient en mode Interruption sur une sortie de menu.
--------------------------------------------------
Simplification d'ecriture , via l'usage
de macro
#define With_SMT1
#define START_SMT1 SMT1_Measure=0;
ST=&SMT1_Measure;SMT1STATbits.RST=1; SMT1CON1bits.SMT1GO=1;
#define STOP_SMT1 *(ST)=SMT1TMRL;
*(ST+1)=SMT1TMRH;*(ST+2)=SMT1TMRU;*(ST+3)=0;
exemple d'utilisation :
#ifdef With_SMT1
// evaluation de la duree fonction Affiche_LCD_Repos();
START_SMT1
Affiche_LCD_Repos();
STOP_SMT1
L1=SMT1_Measure;
L2=L1<<1; // à 500Khz tick=2µS => multiplie
par 2 , à 31,25KHz L1>>5 par 32
sprintf(txt," Duree Affichage LCD , Nb Tics %lu L2=%lu
uS\r\n",L1,L2);
Print(txt);
#endif
// (17:25:07.280)
// (17:25:07.649) Duree Affichage LCD , Nb Tics 181848 L2=363696
uS...... soit 364mS
SOFTWARE :
main_3bus_3xDS18B20_11b_LCD4x20_IT_RB0_RTC_Tests_duree_Appui_BP_via_SMT1_2023-0430.c
_18F27K42_3bus_3xDS18B20_11b_LCD4x20_IT_RB0_RTC_Tests_Duree_Appui_BP_SMT1_2023-0430.hex
Test usage Eeprom 24LC256 pour
stockage des programmations horaires
et autres datas
Taille : 32K bytes
page : 64 bytes
rev 05/05/2023
const char Progr_Name[12]={'C','E','D','M','R','A','J','P','T','V''};
// en hexa : 43 45 44 4D 52 41 4A 50 54 56
programmes W et Z annulés , car
traités differements ...
Les programmes W et Z sont particuliers dans la mesure
où ils « forcent » le fonctionnement à 24/24 et pour
une seule consigne (permanente donc)
*W : Consigne HORS GEL enregistrée à suivre 24/24
* Z : Plus de régulation du tout : Relais Brûleur au
repos
24H/24 et 7 jours/7 ... juqu'au choix d'un autre
programme
Init_I2C();
Test presence devices sur Bus I2C1
@ decimal # 78 soit @Device 7bits = 0X27 PCF8754 for LCD
2x16cars
@ decimal # 174 soit @Device 7bits = 0X57 EEPROM 512bytes
@ decimal # 208 soit @Device 7bits = 0X68 RTC DS3231
xxxxxxxxxxxxxxxxxxxxxxx 24LC256
........................... ABANDON
..... car nombre de programme horaires
reduit à 10 , quelque soit le jour de la semaine
...............................
... => Eeprom du PIC suffisante avec 1ko
Test usage de la Flash pour
contenir les programmations horaires
But : stockage de 12 programmes
possibles pour chacun des 7 jours de la semaine
ATTENTION :
La FLASH tolere 10 000 écritures
seulement (MEM30 EP Memory Cell
Endurance 10k mini)
L'Eeprom petmet 100 000 écritures (MEM20 ED DataEE Byte Endurance 100K mini)
mieux vaut privilégier l' eeprom suivant la cadence (et
donc le nombre) d'écriture/lecture
Nomage des 12 programes :
const char Progr_Name[12]={'C','E','D','M','R','A','J','P','T','V','W','Z'};
// en hexa : 43 45 44 4D 52 41 4A 50 54 56 57 5A
En fait, les 24heures sont organisées en demi-heures
chaque heure sera codé ainsi : 0x00= rien , 0x01= 1ere
demi heure , 0x10= 2em demi heure, 0x11 =Heure entiere
en correspondance directe avec les positions de
caracteres speciaux LCD en CGRAM !
Blanc, barre V.Gauche , barre V.Droite , les 2 barres V.
G et D
Position respective de caractere special : 0,1,2,3
il faut pouvoir stocker :
soit 12x24 = 288 bytes par proramme
sur 7 jours
soit 7x288 = 2016 bytes minimum
un programme hebdomadaire (de travail) sera donc
constitué en RAM par 2016 bytes minimum
PIC Eeprom taile 1Ko ...
insuffisant
PIC RAM 8k0 ...... suffisant,
mais à verifier quand le
programme sera complet
PIC FLASH ... largment de place ..
32ko dispo à cet instant
MAIS , problemo :
du fait de la modularité 128 bytes ecriture en
flash (mode Page)
=> modification de la taille occupée par un programme
24 + 8 datas dummy pour etre modulo 32
bloc de 12x32=384 bytes = 3 blocs de 128 bytes
et pour 7 jours
7*384 = 2688 bytes
avec cette nouvelle donne , exemple de programme
journalier :
dans le projet MPLAB X
délimiter la fin de zone Code , donc ,du debut de la
zone stockage data
dans le projet MPLAB X set project configuration ........customize .............project properties .....................XC8 linker ...........................options : memory model. .........................................rom ranges : ............................................additional options : 0-Max adresse (1FFFF=131071) |
Specify ROM ranges The compiler initially
knows about on-chip ROM only. If external ROM is available then this can be specified via this option. Areas of on-chip ROM that must be reserved can also be listed. Examples: 0-7FF,1000-1FFF ignore on-chip ROM, use only specified ranges; default,3000-3FFF use default on-chip ROM, plus an additional range; default,-7F0-7FF use default ROM, but reserve 16 bytes at 7F0. |
modif option : 0 - 17FFF ... espace 98303 ..131071 dispo pour les datas |
la compilation actuelle du
programme indique alors
on retrouve la limite de code 0x18000 .. ou debut zone
data
le code correspondant à la lecture du programme jour
initialisé en RAM
pour le stocker (Ecrire) en FLASH, puis le Relire apres
coup ( pour le remettre en RAM)
L'operation commence (toujours) par un effacement de la
zone destinataire ( de tailles 3 blocs de 128 bytes)
Dans ce test , la lecture est decomposée modulo 8 bytes
, pour avoir un affichage plus explicite du resultat.
avec l'adresse Flash au debut de chaque (nom de )
programme .
voir code :
#define Debut_Flash_Data
0x18000
18F27K42_Test_ecriture_lecture_zone_Flash_2023-0605.X;inc.txt
Résultat sur terminal :
Debut_Flash_Data=
98304, MAX FLASH Adress= 131071 WRITE_FLASH_BLOCKSIZE=128
sizeof Tables_Progr 10x32= 320
Start chrono SMT1
Erase 3 blocs en Flash à partir de 0x18000
Rempli les 3 blocs avec données de Tables_Progr
relecture Flash -> 12 tables en RAM
98304
00018000 98304 <-------------------------------------------------------
0x18000 ou 98304 en decimal
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, <---
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, <---- 32 bytes
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, <---
0x43, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, <---------- 0x43 = 'E'
00018020 98336
0x11, 0x11, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x45, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
...
etc ........
00018120 98592
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ,
<-------- 0x56=
Stop Chrono, SMT1 = Nb Tics 151627 L2=303
mS
Ce serait donc jouable , mais Risque avec zone FLASH trop
souvent sollicitée ?
à chaque modif => sauvegarde du programme en cours d'utilisation
et du programme modifié !
Décision de Rajouter une Eeprom 24LC256 pour le stockage
des programmes.
=> arret des investigation coté stockage en FLASH PIC
nota : on aurait pu remplacer la 24C32 de la RTC ... mais
il faut etre doué pour dessouder/ressoouder un circuit
CMS
Le principe de stockage reste le
même !
mais couvre tous les autres parametres à sauvegarder..
detail ..voir Stockage 24LC256..
Au final , la solution retenue est
l'usage de l'Eeprom du PIC , avec 1 seul
jeu de 10 programmes (au lieu de 7x10).
Test
Affichage du Programme choisi
13/06/2023
activer la ligne 90 //#define Test_Tables
Test simple en boucle , affiche les 10 tables et reste
sur la derniere
avec rafraichissement / clignotement du caractere (mode
de chauffage) relatif à l'heure en cours
#ifdef Test_Tables Print_Date_Complete(); LCD_Cmd(LCD_CLEAR);__delay_ms(100); LCD_Write_CText_At(1,1," Test Tables Program"); LCD_Write_CText_At(2,1,"F(Progr en cours )"); for ( cx=0; cx<10; cx++) { Rafraichit_LCD_Table_en_cours(cx); CRLF1(); __delay_xSec(2); } // ATTENTION , en sortie de boucle FOR Progr_En_Cours a été incrémenté ! Progr_En_Cours=9; // pour rester sur Table V //---- Clignote l'heure en cours ------- while(1) { // heure RTC en BCD => transformée en décimale Hour=(heure>>4)*10; Hour=Hour + (heure & 0x0F); cx= Tables_Programmations_Horaires_En_Cours[Progr_En_Cours][Hour]; if(Bavard==1) { sprintf(CRam1," Progr en cours %3d cx=0x%X heure BCD en cours 0x%X Hour %3d\r\n",Progr_En_Cours,cx,heure,Hour); Print(CRam1); } cx= Tables_Programmations_Horaires_En_Cours[Progr_En_Cours][Hour]; // change de ligne LCD suivant l'heure if (Hour<12) LCD_Chr_At(3,9+Hour,32); // espace ou code special efface else LCD_Chr_At(4,9+Hour-12,32); // -12 car on est sur 0-24H __delay_ms(500); if (Hour<12) LCD_Chr_At(3,9+Hour,cx); // code de la table programme horaire en cours else LCD_Chr_At(4,9+Hour-12,cx); __delay_ms(500); } #endif |
![]() modif: 1 pixel en moins sur la hauteur de barre verticale , pour maméliorer la visibilté des 2 lignes Programme Horaire |
#ifdef Test_Tables
Print_Date_Complete();
LCD_Cmd(LCD_CLEAR);__delay_ms(100);
LCD_Write_CText_At(1,1," Test Tables Program");
LCD_Write_CText_At(2,1,"F(Progr en cours )");
for ( cx=0; cx<10; cx++)
{
Rafraichit_LCD_Table_en_cours(cx);
CRLF1();
__delay_xSec(2);
}
// ATTENTION , en sortie de boucle FOR Progr_En_Cours a
été incrémenté !
Progr_En_Cours=9; // pour rester sur Table V
//---- Clignote l'heure en cours -------
while(1)
{
// heure RTC en BCD => transformée en décimale
Hour=(heure>>4)*10;
Hour=Hour + (heure & 0x0F);
cx= Tables_Programmations_Horaires_En_Cours[Progr_En_Cours][Hour];
if(Bavard==1) {
sprintf(CRam1," Progr en cours %3d cx=0x%X heure BCD
en cours 0x%X Hour %3d\r\n",Progr_En_Cours,cx,heure,Hour);
Print(CRam1);
}
cx= Tables_Programmations_Horaires_En_Cours[Progr_En_Cours][Hour];
// change de ligne LCD suivant l'heure
if (Hour<12)
LCD_Chr_At(3,9+Hour,32); // espace ou code special efface
else
LCD_Chr_At(4,9+Hour-12,32); // -12 car on est sur 0-24H
__delay_ms(500);
if (Hour<12)
LCD_Chr_At(3,9+Hour,cx); // code de la table programme
horaire en cours
else
LCD_Chr_At(4,9+Hour-12,cx);
__delay_ms(500);
}
#endif
le sous programme d'affichage , caractère par caractère
..
void
Rafraichit_LCD_Table_en_cours(char
Table)
{
int i;
char cx;
cx=Table;
if(Bavard==1) CPrint("Prog en cours :");
PrintChar(cx+48);PrintChar(9);PrintChar(Progr_Name[cx]);
LCD_Chr_At(2,19,Progr_Name[cx]);
sprintf(CRam1,"%c%c:%c%c m ",time[0],time[1],time[3],time[4]);
for (i=0;i<12;i++) *(CRam1+8+i)= Tables_Programmations_Horaires_En_Cours[cx][i];
for (i=1;i<21;i++) LCD_Chr_At( 3,i,*(CRam1+i-1) );
sprintf(CRam1,"%1c %c%c am> ",Progr_Name[cx],*(All_Jour_Semaine+jS*2),*(All_Jour_Semaine+jS*2
+1 ) );
for (i=0;i<12;i++) *(CRam1+8+i)= Tables_Programmations_Horaires_En_Cours[cx][i+12];
for (i=1;i<21;i++) LCD_Chr_At( 4,i,*(CRam1+i-1) );
}
videos :
Chaudiere_Tests_Progr_horaires_2023-0615.webm
Schéma
et Prototype Hardware pour les tests
version pdf : Schema V14.0.0.pdf
réalisé sous Kicad 5.1.7
nota :
les leds du prototype sont ici, sur les BP ... pas sur
les sorties LED comme sur le schema
Les 3 sondes DS18B20 ont chacune leur propre bus OWS.
Alimentation 5V DC
Pickit4 pour le chargement du fichier *.Hex , lié à
MPLABX 6.00 IDE
TEST HARDWARE
28/07/2023
1ere Mise sous tension :
Alim 230V AC/ 9V DC ( limitée à 1A maxi)
avec Amperemetre classique en serie ..200mA !!
LCD tres lumineux ( trop lumineux) !
Mesure Vcc 9V au lieu de 5V ! ..
STOP !
A l'ohmetre, le +5V sonne avec le fusible 12V et vice
versa ,le 12V avec le fusible 5V ..
Il s'avere que la sortie et l'entrée LM 7805 sont
inversée
29/07/2023
.....Modif Hardware :
Coupé les liaisons Pin1 et Pin3 sorties
LM7805 vers le C.I., pour pouvoir les inverser
en rajoutant 2 straps croisés .. pas facile .. mais ...OK
voir
detail ici
Test séparé du PIC18F sur
support ZIF
Avec une configuration Hardware la plus simple possible
et rapide à mettre en oeuvre .
...il (le PIC) ne semble pas avoir souffert .. car
toujours possible de charger un programme, avec sortie de
message UART OK
Dans ce cas de figure, le Pickit alimente le PIC18F en +5V.
(option Power)
1er essai chargement de programme :
PROBLEME AVEC ICSP in situ (sur la carte
!)
message Pickit4
Transmission on endpoint 2 failed (err
= -10121)
A communication error with the debug tool has
occurred. The tool will attempt to recover momentarily.
Connection Failed.
Transmission on endpoint 2 failed (err = -10121)
passé sur MPLAB IPE
probleme idem ...
mesure à l'ohmetre ( hors tension !) il y a 4.7k sur RC7
(entre RC7 et +Vcc)
Modif MPLAB IPE Settings
Pickit4 Tool Options(s)
PGC config None
PGD config None
2em essai ICSP , chargement de programme
...OK
Programming/Verify complete
2023-07-29 11:46:59 +0200 - Programming complete <--
OK
2eme Mise sous tension
:
Mesures :
sans les modules LCD,RTC,PIC18
U Alim = + 12.17V
U Vdd= + 5.08V
Avec les modules LCD,RTC et PIC18
U Alim= + 12,04V
U Vdd= + 5.08
V
Consommation ( mesure avec Multimetre en mA) => 39 à
42 mA
Rien sur LCD !
sur terminal YAT :
Init_I2C() à 100Khz;
Test presence devices sur Bus I2C1
@ decimal # 64 soit @Device 7bits = 0X27 PCF8754 for LCD
2x16cars
car j'ai un LCD Bleu 4x20 avec PigBack I2C adapteur au
dos du LCD , adresse 0x27,sur Prototype Breaboard)
sur la carte , il ya un LCD Blanc classique + PCF8574
séparé ..adresse 0x20
d'ou modif programme LCD_4bits_I2C_2023-0713.h
//PCF8574 pour LCD 2x16 avec A0,A1,A2 au niveau logique 0
#define LCD_ADDR 0x20 //PCF8574 externe LCD 4x20
Blanc
// #define LCD_ADDR 0x27 //PCF8574 inclus en Pigback sur
gros LCD 4x20 Bleu Paul
Rechargement du programme modifié,
Init_I2C() à 100Khz;
Test presence devices sur Bus I2C1
@ decimal # 64 soit @Device 7bits = 0X20 PCF8754 for LCD
2x16cars
adresse LCD= 32 soit 0X20
Possibilité d'affichage du LCD
de cette carte ( écriture noire sur fond blanc)
2 autres petites modifs :
* inversion sens action des 2 led Confort et Eco
..car surmon prototype breadboard les leds etaient
tirées au +VCC (+5.0V)
alors que sur la carte, elles sont tirées au Vss (0v)
*
modif void Print_Date_Complete(void)
au lieu de mois et année 00002 Juillet
23 14H08M17S manque le jour !
.....devient 00008 27/07/23 15H14M30S
ainsi que manque de parentheses sur le test if( Bavard & 0x02==2)
... devient if( (Bavard
& 0x02==2)
Message LCD à peine visible
=> il faut ajuster le
potar "Contraste" et ensuite
Potar "Luminosité" !
Affichage LCD ..OK
Rajout des 3 capteurs de températures TO92 OWS DS18B20
.. ( capteurs non triés, triés c'est 3 fois plus cher!))
Implantation 3 capteurs DS18B20
Liaison UART
Liaison ICSP vers Pickit4
nota : montage provisoire Pile CR2032
au lieu de accu LIR 2032 sur module RTC !
Lancement du programme avec procedure Spéciale "demande Egalisation"
suite à la mise en place des 3 capteurs DS18B20
Appui sur BP ROUGE (RESET) maintenu ,
appui sur BP VERT( demande égalisation)
Maintenu
relache BP ROUGE Reset
le programme demarre
execution de Init Oscillateur, et Init Hardware
Attendre > 4 secondes et relacher
SW6 BP VERT
execution initilalisations peripheriques : UART, I2C, 3
bus OWS
Mesures brutes
T1.INTER.= 31.125°C <-- écarts relativements
importants entre ces capteurs non triés
T2.EXTER.= 29.750°C
T3.EAU .= 29.312°C
MOYENNE .= 30.062°C
Rechargement corrections capteurs DS18B20
depuis Eeprom
T1Cor= -1.062
T2Cor= 0.312
T3Cor= 0.750
Mesures 3 temperatures Corrigees :
INT_mes= 28.437°C
EXT_mes= 29.812°C
EAU_mes = 30.250°C
Attente remise en place des 3 capteurs,et RESET
pour sortir
Appui sur BP ROUGE Reset, relance le
programme
sans faire de demande d'egalisation, les corrections de
temperatures etant relues à partir de l'eeprom PIC.
en fin d'initialisation le LCD affiche sa page de repos ,
qui est rafraichie à chaque tour de boucle programme (
<3sec)
et le terminal, seulement la valeur du compteur de boucle
de programme 0 ..65535..0..etc
car, par défaut mode Bavard=0
!
00000
00001
00002
Mesure consommation de l'ensemble , avec rajout du module
HC05 blueTooth :
reste < à 80mA
Tension aux bornes du régulateur LM7805 -> 12-5 = 7V
Puissance dissipée : 7x 0,08 = 0.56 W => OK
* Mesure de la temperature du LM7805 (équipé d'un
radiateur) à 28°C ambiant => 37°C
Nouvelles présentations affichage
LCD repos
pour en améliorer la lisibilité
le 1er caractere representant l'etat du Bruleur : en
position L1C1
Bruleur OFF => rien ( 1 blanc)
Bruleur ON => alterance entre '*' et 'carré noir' à
chaque tour de boucle programme ..
Nota : Test possible via commande clavier BRU=1 ou BRU=0
La valeur de compensation ressenti ( 0.0 à +2.0°C ) ne
s'affiche que si >0.0
La Lettre G est le coeff Energetique de la chaudiere
Les 3 sondes DS18B20 (formt TO92) sont connectées
directement sur la carte pour les tests.
Test affichage 7em car. special sur LCD ( fonction du
choix Correcteur Energetique)
Classement énergetique
suivant le critere : Choix_NRG_cor
int NRG_cor[]={45,38,32,27,26,20,18,19};
//tableau de correspondance parmi A, B, C, D , E, F, G ,..H
int Choix_NRG_cor=6; //facteur de performance
énergétique
ce qui conduit à l'usage de Lettre en video inverse
definies par cette table :
const unsigned char LCD_Custom_Chars_Set2[64] =
{// rev 02-07-2023
//---------- set #2 ------------------
0xff, 0xf3, 0xed, 0xed, 0xe1, 0xed, 0xed, 0xff, //A
0xff, 0xe3, 0xed, 0xe1, 0xed, 0xed, 0xe3, 0xff, //B
0xff, 0xf1, 0xef, 0xef, 0xef, 0xef, 0xf1, 0xff, //C
0xff, 0xe3, 0xed, 0xed, 0xed, 0xed, 0xe3, 0xff, //D
0xff, 0xe1, 0xef, 0xe3, 0xef, 0xef, 0xe1, 0xff, //E
0xff, 0xe1, 0xef, 0xe3, 0xef, 0xef, 0xef, 0xff, //F
0xff, 0xf1, 0xef, 0xef, 0xe9, 0xed, 0xf1, 0xff, //G
0xff, 0xed, 0xed, 0xed, 0xe1, 0xed, 0xed, 0xff //H
};
Hors , on ne peut avoir qu'une
seule table de 8 caracteres en CGRAM LCD active !
Changer de table ne va pas, car alors les autres
caracteres prédéfinis seraient écrasés !
Il faut donc modifier en temps reel, QUE LE CARACTERE
CONSIDERE ..
Heureusement, Il n'est utilisé qu'à 1 seul endroit sur
l'affichage LCD, et ne sera modifié que tres rarement
voir jamais plus .. apres la derniere mise au point ...
Rappel :
La CGRAM comporte 64 bytes, 8 chars definis par 8 bytes
Le premier est en position 0 .. le dernier en Position 7
Pour l'afficher , on ne modifiera que la definition du 7em
char ( en position 6 ) CGRAM directement , de sorte à ne
pas
affecter ceux déja stockés en CGRAM .. C'est possible
via l'adressage CGRAM qui debute en 0x40H
Le 7em element se trouve à la position (7-1)*8= 48 donc
adresse 0x40 + 48 -> 0x70H
un petit BEMOL .. le choix H est remplacé par une
consigne CFT_csg !
video: LCD_affichage_2023-0705.webm
... à suivre ..
rev 02-07-2023 :
Abandon des caracteres en
Videos Inversés
=> nouvelle definition des caracteres speciaux dans LCD_chars_Speciaux_2023-0817.h
//---------- set #1 ------------------
const char LCD_Custom_Chars_Set1[64] ={ //position offset
libelle
0x00,0x00,0x00,0x00,0x00,0x1B,0x1B,0x00, // 0 0 Eco
0x00,0x18,0x18,0x18,0x18,0x1B,0x1B,0x00, // 1 8 barre G 1ere
demi heure en CONFORT
0x00,0x03,0x03,0x03,0x03,0x1B,0x1B,0x00, // 2 16 Barre D
2em demi heure en CONFORT
0x00,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00, // 3 24 barre GD
heure en CONFORT
0x04,0x0E,0x1F,0x04,0x04,0x04,0x04,0x00, // 4 32 Fleche
HAUT
0x04,0x04,0x04,0x04,0x1F,0x0E,0x04,0x00, // 5 40 Fleche
BASSE
//0x00,0x0A,0x04,0x1F,0x04,0x0A,0x00,0x00,
// 6 48 BRULEUR
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x00, // 6 48 Noir
0x0E,0x0A,0x0E,0x00,0x00,0x00,0x00,0x00 // 7 56 Degre
celcius
};
const char Special_Name1[8][8]=// libelé pour caracteres
Speciaux sur 7 chars+zero
{"ECO....", "BARRE_G", "BARRE_D",
"BARREGD", "FLECH H", "FLECH_B",
"NOIR...", "DEGREC "};
Nota : le caracteres special NOIR peut etre remplacé par
le caractere ascii 255 de la CG ROM !
===> le 7 car special CG RAM est donc à disposition
..
Test2 : Affichage en clair, des
plages Horaires d'un programmation Horaire
Affichage Plages Horaires ,correspondant
à la table de programmation affichée
Les 2 premiers programmes ne sont pas concernés , car
choix constant du mode pendant 24H.
reste donc 8 programmes concernés.
rajout compilation conditionelle :
#ifdef TEST2
#include "TEST2_2024-0324.inc"
"endif
il faut retrouver les changement de mode CONFORT ou ECO
correspondant
pour en afficher les plages d'actions ..jusqu'à un
maximum de 6 plages ..
Affichées en ligne 1 et 2 du LCD
code TEST2 :
YAT Terminal :
--------- Zone Test 2 24-03-2024
----------------
Lecture table programmes horaire en eeprom
Relecture datas eeprom :
Flag Run Once at @ 0x0000 =99
Programme version : 240322
0x00A0 Nom : CF*2424
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03,
0x00C0 Nom : EC(2424
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00E0 Nom : DOMUS>R
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00,
0x0100 Nom : MATIN>W
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00,
0x0120 Nom : RMidi>W
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x03, 0x00, 0x00, 0x03,
0x03,
0x03, 0x00, 0x00, 0x00,
0x00, 0x03, 0x03, 0x03,
0x03, 0x03, 0x00, 0x00,
0x0140 Nom : AMidi>W
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
0x00, 0x00,
0x0160 Nom : JOUR>W
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00,
0x0180 Nom : P>Pers1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
0x00, 0x00,
0x01A0 Nom : T>Pers2
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x03, 0x03, 0x03,
0x01, 0x00,
0x01C0 Nom : V>Pers3
0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03,
0x03, 0x03,
0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00,
Decodage table de programmation sauf CONF24/24 et ECO 24/24
car sur 1 seule plage
choix Numero de programme ? saisir PRG=x (avec x=2 à 9 )
x=Q pour Sortir
PRG=4
Recu :PRG=4
new prog en cours # 4 R
Decodage Table #4:RMidi>W
Plage 1H :*06h
Plage 1B :(08h
Plage 2H :*11h
Plage 2B :(13h
Plage 3H :*17h
Plage 3B :(22h
------------
choix Numero de programme ? saisir PRG=x (avec x=2 à 9 )
x=Q pour Sortir
PRG=Q
Recu :PRG=Q
.. poursuite du
programme normal
Init Timer2 100mS
Duree Affichage LCD repos via Timer2 3 *100mS
via SMT1 : Nb Tics 186777 ,L2=373 mS
..etc ....
------- BUGS et problèmes
rencontrés ---------------------------....
Probleme Affichage LCD
Le Menu #05 (MAJ RTC Manuelle) interfere avec l'affichage
LCD Repos
Les lignes 3 et 4 , affichant la programmation horaire
via des caracteres spéciaux LCD ( char 0,1,2,3)
sont perturbées par l'affichage residuel du Menu #05
la capture des bytes affichés (via YAT terminal) donne :
0.0.1.1.1.2.2.2.3.3.3.3. <-- ici en ascii par rajout de 48 aux
valeurs Ligne 3 LCD de position 8 à 20
3.3.2.2.2.1.1.1.0.0.0.0. <-- ici en ascii par rajout de 48 aux
valeurs Ligne 4 LCD de position 8 à 20
Il s'avère que l'usage de string (Chaine
de caratere) s'affiche meme avec des valeurs
nulles à l'interieur ..
La ligne 3 est affichée entierement malgré la présence
d'un Zero à la 8em position !
C'est ANORMAL !
Recherches de bug dans MAJ RTC Manuelle .... rien trouvé
=> donc Remise en cause Affichage LCD Repos
et plus particulierement dans la gestion affichage Ligne
3 et 4 des caracteres speciaux (prorammation horaire)
Nota : les autres lignes 1 et 2 sont contenues
respectivement, chacune dans un string de 20 carateres
il n'y a pas de gestion fin de string .. car la sortie de
boucle se fait via NBCARPL maxi atteint
Verif. fonction affichage :
//-------
LCD ligne 3 --- !
CRam1[0]=0; //12345678901234567890
sprintf(CRam1,"%c%c:%c%c m ",time[0],time[1],time[3],time[4]);
if(Bavard==8)
{ CRLF1();
}
// 1ere partie MATIN
for(i=0;i<12;i++) <---------------
Complete le contenu de CRam1 avec le contenu de
Programmation Horaire (matin 00H à 11H00)
{
cx=Table_Progr_Horaire_utilisee[i];
*(CRam1+8+i)= cx;
if(Bavard==8)
{ PrintChar( cx+48);
PrintChar('.');
}
}
if(Bavard==8) CRLF1();
LCD_Write_Text_At(3,1,CRam1);
<--- CRam1 est un String contenant des valeurs nulles
:caractere special 0)! et pourtant Affichées!
Ecriture d'un string dans LCD
avec version Affiche_LCD_Repos_2023-0912.inc
void LCD_Write_Text_At(
char Ligne, char Col, char * t1) { LCD_At(Ligne,Col); LCD_puts(t1); } void LCD_puts( char *s) { int i; i=0; //sortie si caractere pointé null et i>20 while((*(s+i) != 0) && (i<NbCarPL)) { LCD_Data(*(s+i)); // LCD_putch(*(s+i)); Delay_10us(); i++; } } |
![]() |
affiche programmation horaire ligne 3 positionr#8 à 20 |
void LCD_Write_Text_At(
char Ligne, char Col, char * t1)
{ LCD_At(Ligne,Col);
LCD_puts(t1);
}
void LCD_puts(
char *s)
{ int i;
i=0;
//sortie si caractere pointé null et si i>20
while((*(s+i) != 0) && (i<NbCarPL))
{
LCD_Data(*(s+i)); // LCD_putch(*(s+i));
Delay_10us();
i++;
}
}
Gros doute sur le
&& LOGIQUE
un test d'envoi d'une chaine de caratere de longueur <
20 caratere
n'est pas tronquée ! ...pas de detection du zero
terminator
Modif : Remplacement du Test && logique
par Test Arithmetique &
void
LCD_puts( char *s)
{ int i;
i=0;
//sortie si caractere pointé null ET i>20
while((*(s+i) != 0) & (i<NbCarPL))
// ....modif 26-10 was &&
{
LCD_Data(*(s+i)); // LCD_putch(*(s+i));
Delay_10us();
i++;
}
}
La ligne 3 se retrouve bien tronquée au 8em char ...NORMAL
, car rencontre un caractere special = 0 !
---------------------------------------------------------------------
la doc microsoft n'est pas claire , quelque chose m'echappe
!
Opérateur Description
Les opérateurs logiques neffectuent
pas les conversions arithmétiques habituelles.
Au lieu de cela, ils évaluent chaque opérande en termes
déquivalence à 0.
Le résultat dune opération logique est 0 ou 1. Le
type du résultat est int.
&& Lopérateur ET
logique produit la valeur 1 si les deux opérandes ont
des valeurs différentes de zéro.
Si au moins un des opérandes est égal à 0, le
résultat est 0.
Si le premier opérande dune opération ET logique
est égal à 0, le second opérande nest pas
évalué.
------------------------------------------------------------------------
Modification d'affichage pour les
lignes 3 et 4 avec char speciaux
Au lieu d'utiliser un string, usage direct du contenu de
la table (Table_Progr_Horaire_utilisee[i];)
avec envoi Byte par Byte du contenu.
//-------
LCD ligne 3 ---
CRam1[0]=0;
sprintf(CRam1,"%c%c:%c%c m ",time[0],time[1],time[3],time[4]);
CRam1[8]=0;
LCD_Write_Text_At(3,1,CRam1); // exemple affichage "21:54
m " en debut ligne 3
// 1ere partie programmation MATIN (m)
// depart position LCD Ligne 3 deplacement X=9
for(i=0;i<12;i++) // de 00H 00 à 11H59
{
cx=Table_Progr_Horaire_utilisee[i];
LCD_Chr_At(3,i+9,cx);
__delay_us(100);
if(Bavard==8)
{ PrintChar( cx+48); // rajout de 48 pour avoir un
caractere imprimable ascii
PrintChar('.'); // separateur de donnée
}
}
if(Bavard==8) CRLF1();
...Traitement idem pour Ligne 4
Petit test de verification ( en
mode string)
LCD_Cmd(LCD_CLEAR);
__delay_ms(100);//__delay_xSec(1);
CPrint( " test LCD_Write_CText_At( \r\n");
strConstRamCpy(CRam1,"12345678901234567890");
LCD_Write_Text_At(1,l,CRam1);
*(CRam1+15)=0;
LCD_Write_Text_At(2,l,CRam1);
*(CRam1+10)=0;
LCD_Write_Text_At(3,l,CRam1);
*(CRam1+5)=0;
LCD_Write_Text_At(4,l,CRam1);
Les lignes 2,3,4 s'affichent bien tronquées au bon
endroit ...
Plus d'interference avec MAJ RTC Manuelle et Affichage
LCD Repos ..OK
Contre-essai :
usage de & au lieu de &&
Il s'avere que l'usage de
&& ou & amèene à la même conclusion et
que....
... je n'ai pas
découvert POURQUOI ça tombait en marche , en utilisant
LCD_Write_Text_At(
char Ligne, char Col, char * t1)! , définit dans Affiche_LCD_Repos_2023-0912.inc
L'essentiel est d'avoir
éliminé ce BUG latent !
---------------------------------------------------------------------------------------------------------
Probleme
avec usage du Timer2
utilisé en Timer Compteur ... n'incrémente
pas Cpt2 chaque 100mS
Il est utilisé pour mesurer la durée de la boucle
principale de programme ( avec aussi SMT1 pour mesure
plus precise et confirmer)
Init Timer 2 pour un timing de 100mS , interruption
vectorisé en mode LOW PIORITY
..Cpt2 reste à 0 , car on n'a pas d'interruption Timer2
!
Les autres interruptions RB0 et UART sont OK , mais en
mode HIGH PRIORITY..
Probleme au niveau de la
Configuration interruptions, rajout
armememnt bit GIEL
void
Interrupt_Init(void)
{
bool state = (unsigned char) INTCON0bits.GIE;
INTCON0bits.GIE=0;
INTCON0bits.IPEN = 1;
INTCON0bits.GIEH = 0; // dis high priority interrupts
INTCON0bits.GIEL = 0; // dis low priority interrupts*
INTCON0bits.IPEN = 1; // Enable interrupt priority
// __asm("BCF INTCON0,GIE");
// GIE = 0;
IVTLOCK = 0x55;
IVTLOCK = 0xAA;
IVTLOCKbits.IVTLOCKED = 0x00; // unlock IVT
IVTBASEU = 0;
IVTBASEH = 0;
IVTBASEL = 8;
IVTLOCK = 0x55;
IVTLOCK = 0xAA;
IVTLOCKbits.IVTLOCKED = 0x01; // lock IVT
// Assign peripheral interrupt priority vectors
IPR3bits.U1RXIP = 1;
IPR1bits.INT0IP = 1;
IPR4bits.TMR1IP = 0;
IPR3bits.TMR0IP = 0;
IPR4bits.TMR2IP = 0; //
low priority
IPR7bits.TMR4IP = 0;
IPR9bits.TMR6IP = 0;
IPR0bits.IOCIP = 0;
INTCON0bits.GIEL = 1; //
Enable low priority interrupts..pour Timer2 !
INTCON0bits.GIEH = 1; //Enable high priority interrupts
INTCON0bits.GIE= state;
}
Traitement de l'interruption TIMER 2 :
void
__interrupt(irq(IRQ_TMR2),low_priority)TMR2_ISR(void)
{
//U1TXB='%';
Cpt2++;
Flag_Timer2=1;
// if (Cpt2>4) Drapeaux.Tmr2_Elapsed=1; // 250x4mS =>
1sec
if (Cpt2>10) Drapeaux.Tmr2_Elapsed=1; //100mS x10 =>
1sec
PIR4bits.TMR2IF=0;
}
verification :
Recu :BAV=4
HH =14 MM=31 Mode_Conf_Eco=Cf second=3 Timer2=> 26 x 100mS
SMT1 =>2608204 uS .... OK
00020 Mercredi 25/10/23 14H31M06S
*** ATTENTION ****
Meme si on n'utilise pas les interrupt IOC
Laisser IOCBN=0x7E ; //detection front descendant (Negatif)
sauf RB7 et RB0;
... pour la detection du Switch actionné en front
descendant !
via la lecture de :
Etats_BP =IOCBF >> 1 ; dans l'interrupt RB0
---------------------------------------------------------------------------------------------------------
Attention à bien séparer les
opérations, avec des parenthèses
23/03/2024
probleme : plus de mesure de temperature
OWS = 0.000!!!
suite modif DS18B20_2024.c pour simplifier l'ecriture
suivante avec :
// temperature1 =( ( scratchPad[1] * 256.0) + scratchPad[0]
)*0.06250;
Lx= scratchPad[1] <<8
+ scratchPad[0];
temperature1=Lx *0.062500; //Resolution <----- BAD ..mesure
=0.00
...mais OK avec usage de parentheses
Lx=(scratchPad[1] <<8)+
scratchPad[0];
temperature=Lx * 0.0625; <--- mesure OK
rappel:
The scratchpad memory contains the 2-byte temperature
register that stores the digital
output from the temperature sensor
MSB+LSB = 0550h= 1360 => 1360 *0.0625= 85°C par
defaut
-----------------------------------------------------------------------------------------------------------
BUG sur Menu10.2
Sur une selection de variable , déja positionnée sur sa
valeur Maxi ou Mini
on entre pas dans le test
exemple :
si NRGind est deja à la valeur 'H'
if ( (Step==14) && (cx < 'H') )
{
cx=cx+1;
sprintf(CRam1,"NRGind* %c",cx);
}
Print(CRam1);CRLF1();
if(Step<14) *(CRam1+9)=7;
LCD_Write_Text_At(SPas,1,CRam1);
__delay_ms(200);
LCD_Chr_At(3,12,' ');
LCD_Chr_At(4,12,'>');
Etats_BP=0;
Restart_Timeout();
On affiche alors un contenu
de CRam1 quelconque, issu d'une operation
precedente !
La partie affichage ne peut donc pas etre commune, et
doit etre incluse
dans le test lui meme ..
Modif :
if ( (Step==14)
&& (cx < 'H') )
{
cx=cx+1;
sprintf(CRam1,"NRGind* %c",cx);
Rafraichit_Ligne_Menu_LCD(0);
}
avec
void Rafraichit_Ligne_Menu_LCD(char
degr)
{
Print(CRam1);
CRLF1();
if (Degr>0) *(CRam1+9)=7; // remplace le . par le
sigle degré
LCD_Write_Text_At(SPas,1,CRam1);
}
De plus ,ce Bug existait déja sur le Menu 10.1 ..corrigé
-------------------------------------------------------------------------------------------------------
===== pour mémoire
====================
Old versions
GESTION
DES MENUS...SW0
Menus appelés depuis l'appui sur BP SW0 pendant
< 1 sec ,
Appel détecté par une interuption INT0 sur pin MCU RB0
(SW1..SW5)
Choix en fonction de la valeur de MPas
Ordinogramme détaillé :
nota : les sortie messages sur terminal n'apparaissent
pas dans l'ordinogramme ,
pour ne pas surcharger celui-ci .
Chaudiere_Menu_Consignes_10.1_2023-1204_Drawio.pdf
Chaudiere_Menu_CONSIGNES_10.1_2023-1204.drawio
Libelles des Menus via SW0 :
//
---- MENUS via acces SW0 < 1 sec ---------
while( Menu==10)
{ // ordre des menus suivant Dossier
Chauffage (V5.0.1).xls
if (Bavard==9)
{ sprintf(CRam1," Menu= %3d MPas= %3d \r\n",Menu,MPas);
Print(CRam1);
}
switch (MPas)
{
case 1 : MENU_CONSIGNES(); break;
// consignes Confort et Eco
case 2 : MENU_Temp_Mini_Exter(); break;
case 3 : MENU_Temp_EAU_Chaudiere(); break;
case 4 : MENU_Compens_T_Ressentie(); break;
case 5 : MENU_Temp_Hors_Gel(); break;
case 6 : MENU_Hysteresis() ; break;
case 7 : MENU_Indice_Energetique() ; break;
}//switch MPas
}
voir MENU10_1234567_2024-0327.inc
Deroulement des menus
par appui successif de SW0 (duree<
1 sec) :
00901
# 00902
MENU10.1 CONSIGNES
Consigne Cf 19.0C
Consigne Ec 15.0C
# Sortie CONSIGNES CFT ECO
Boucle sur Menu10.2
Menu 10.2 Temp_Mini_Exter
# Sortie Temp_Mini_Exter
Boucle sur Menu10.3
Menu10.3 Temp_EAU_Chaudiere
# Sortie Temp_EAU_Chaudiere
Boucle sur Menu10.4
Menu10.4 MENU_Compens_T_Ressentie=
0.0
# Sortie Compens_T_Ressenti
Boucle sur Menu10.5
Menu10.5 via SW0 MENU_Temp_Hors_Gel
# Sortie Temp_Hors_Gel
Boucle sur Menu10.6
Menu10.6 SW0 Hysteresis
# Sortie Hysteresis
Boucle sur Menu10.1
............ on a fait 1 tour
complet !..........
le # represente un
appui de touche détecté via Interruption INT0 (RB0).
Remarque :
Vu la possibilité de ce MCU avec 128K programme, j'ai
privilégier l'étalement et la simplicité du code ,
pour en faciliter la lecture , au detriment de la
longueur de celui ci ..
Dans de multiples cas de figure on pourrait utiliser des
pointeurs sur variables et sur le pas de modfification
comme arguments , pour avoir des subroutines communes ...
C'est donc PERFECTIBLE .. ne vous géner pas pour
faire des propositions en ce sens
.. mais sans tout chambouler le programme principal et EN
RESPECTANT le cahier des charges ...
rajout libéllés des menus10.x
const char Menus_SW0[][]=
{ {"CONSIGNES CFT ECO
"},
{"Temp_Mini_Exter "},
{"Temp_EAU_Chaudiere"},
{"Compens_T_Ressenti"},
{"Temp_Hors_Gel "};
{"Hysteresis "};
{"Indice NRG "};
rajout sortie commune aux appels des 7 Menus via
SW0
Traitement des 7 menus accessibles
via SW0 :
rev 27/03/2024
MENU10_1234567_2024-0327.inc
Menu 10.1 ....CONSIGNES Confort et Eco
rev 2023.
En reference : document
Dossier
Chauffage (V5.0.1).xls
Procédure Affiche_MENU_CONSIGNES(),
On commence par :
* Transfert des consignes CFT_csg et ECO_csg dans des
variables temporaires , respectivement Dummy1 et Dummy2
*choisir quelle consigne on veut modifer SW2 -> CFT ,
ou SW3 ->ECO, ....un sigle > se met en face de la
ligne Seelctionnée
*validee le choix entre Confort et Eco par SW1
*choisir entre Incrementer ou diminuer ladite consigne SW2
+, SW3 -
*Valider la modification => variable temporaire
transférée dans CFT ou ECO par SW1
*Validation Memorisation en Eeprom CFT ou ECO -> en
Eeprom de travail par SW4
Nota : au cours du Menu, un appui sur SW0 ou un timeout
de 10 sec fait sortir du menu
Deroulement vu coté YAT Terminal : Test void Affiche_MENU_CONSIGNES() 00027 Mercredi 06/12/23 17H11M11S 00028 Mercredi 06/12/23 17H11M13S # 00029 Mercredi 06/12/23 17H11M16S Duree = 48 mS , BP=0X01, Menu= 10 SW0 MENU10.1 CONSIGNES Consigne Cf 19.0C Consigne Ec 15.0C #> Consigne Cf 19.0C #SW1 valide choix Cf #> Consigne Cf 19.5 augmente consigne CFT 19.5 #> Consigne Cf 20.0 augmente consigne CFT 20.0 #> Consigne Cf 20.5 augmente consigne CFT 20.5 #Valid. modif # Memo Modif consigne : CFT_csg =>20.5 en Eeprom Travail ..@00064 Sortie Normale Menu_CONSIGNES CFT ECO Confort modifiee 00030 Mercredi 06/12/23 17H11M44S 00031 Mercredi 06/12/23 17H11M46S le # represente un appui de touche détecté via Interruption. |
![]() Old version 2023 ! |
extrais software (version 2023):
MENU10_1_2024-0331.inc:
...... modifié en 2024 .......
Menu 10.2 .....Temperature Mini Exterieure
Affiche_MENU_Temp_Mini_Exter
rev ........2023.
case 2 : Affiche_MENU_Temp_Mini_Exter();
Execution : # 01021 MENU10.1 CONSIGNES Consigne Cf 19.0C Consigne Ec 15.0C # Sortie CONSIGNES CFT ECO Boucle sur Menu10.2 Menu 10.2 Temp_Mini_Exter #Exterieur mini -5.0C #Exterieur mini 0.0C #Exterieur mini -5.0C #Exterieur mini -10.0C #Exterieur mini -15.0C #Exterieur mini -20.0C # SW4 ON Save -> eeprom Param+8 Sortie Normale Menu_Temp_Mini_Exter 01022 |
![]() version 2023 |
Menu 10.3 ......Temperature Eau Chaudiere
............rev 30/03/2024
Dans le main programme , SI Menu=10 et MPas=3
Entrée dans ce menu via appel successif SW0 , traité
via interruption
MPas s'incremente à chaque appui sur SW0<1sec
case 3: Affiche_MENU_Temp_EAU_Chaudiere();
Choix via SW1 < 1sec de la
variable (ligne LCD repérée via le sigle '>'
Valider la Selection du choix par SWL > 1sec
Rappel convention : SW1 appui court (<1sec) , SW1L
appui long (>1sec)
le sigle '>'
devient '*'
incremente la variable designée via SW2, ou decremente
via SW3
dans des limites imposées , ainsi que le pas de
progression .
SW4>1sec pour valider la modif. .. puis sauvegarde en
Eeprom.
ou SW0 pour sortir SANS modifier..
Un timeout 10sec ou appui sur SW0 fera sortir du menu.
Memo en Eeprom :
80 Org_Sauve_Param_Travail+ 0 , CHD_min
84 Org_Sauve_Param_Travail+4 , CHD_max
video :
Test_menu10.3_CHD_max_2024-0330.webm
Menu 10.4 .....Compensation Temperature
Ressentie
* COMPENSATION Ressenti * SW2/SW3 appui court : Incrémente / Décrémente * SW1 appui long : Enregistre en Eeprom et passe au pas suivant * SW0 appui long Quitter ou sortie TimeOut 10 sec. nota: concerne la variable INT_cor |
![]() |
Code du sous-menu MPAS=1
Execution : apres 2 incrementation de +0.5°C 00007 # 00008 Duree = 198 mS , BP=0X01, Menu= 10 SW0 Menu10 via SW0 Mpas= 1 : MENU_Compens_T_Ressentie COMP.Ressenti 0.0 # COMP.Ressenti 0.5 ### COMP.Ressenti 1.0 # Save -> eeprom Param+12 Sortie MENU_Compens_T_Ressentie 10 sec ecoulée .. 00009 00010 nota: la valeur INT_cor n'est affichée sur Affichage LCD Repos que si > 0.0 |
le code de cette partie :
Affiche_MENU_Compens_T_Ressentie.X_2023-1026.inc
Menu 10.5 ........Temperature Hors Gel
case 5 : Affiche_MENU_Temp_Hors_Gel(); break;
Execution Boucle sur Menu10.5 Menu10.5 via SW0 MENU_Temp_Hors_Gel #Consigne H.Gel 10.0 #Consigne H.Gel 9.0 #Consigne H.Gel 8.0 #Consigne H.Gel 7.0 # Save -> eeprom Param+12 Sortie Normale Menu_Temp_Hors_Gel 00003 |
![]() |
Menu 10.6 ......Hysteresis sur mesures
Temperatures
rev 09/03/2024
rajout traitement Menu 10.6
void MENU10_6_Hysteresis(void)
Software : SW1 est utilisé pour changer le choix de sonde Je n'utilise qu'un seul BP pour parcourir VERTICALEMENT les lignes LCD 2,3,4,2.etc ...en boucle de HAUT en BAS uniquement cela evite de rajouter un traitement suplementaire direction vers le HAUT via un autre BP Je n'ai pas rajouté de confirmation de choix de ligne ...alourdi trop le programme SW0 sert à sortir du menu (abandon des modifs eventuelles) le Timeout 10sec peut aussi faire sortir du menu ! Le time out est reinitalisé apres chaque appui de BP . Usage de variables intermediaires (F1,F2,F3) pour faire les modifs BP SW2(+) et SW3(-) pour modifier la valeur pointée par la ligne active sur LCD ( sigle > sur le 1er caractere de la ligne ) Variables HYS_xxx modifiéees QUE si validées via appui sur SW4 > 1sec Stockage des valeurs modifiées en zone eprom Travail voir Define_Org.h #define Org_Sauve_Param_Travail 0x0050 // origine =80 en decimal et Dossier Chauffage_V5.0.1_B.xls pour la definition des adresses en Eeprom HYS_int 124 0x007C -0.5 Valeur Hystérésis de Reprise (Sonde INT) ; Arrêt = 0 0,5°C HYS_ext 128 0x0080 -0.5 Valeur Hystérésis de Reprise (Sonde EXT) ; Arrêt = 0 0,5°C HYS_eau 132 0x0084 -2.0 Valeur Hystérésis de Reprise (Sonde EAU Chaudière) ; Arrêt = 0 1,0°C => offset HYS_int= 124-80 = 44 |
|
Menu_10.6_Hysteresis_2024-03.drawio.pdf |
Déroulement sur YAT Terminal :
Test SW6 pour demande
Egalisation ou Restauration Usine
Duree Appui : 0
Presentation :
PIC18F27K42 + 3x OWS sensor DS18B20 sur RA0,RA1,RA2
Directory :C:\MPLABX_Projects\Chaudiere_Controle_18F27K42_2024.X
Project : Chaudiere_Controle_18F27K42_2024
Source : main.c , rev :_2024-0309
Config Internal Fosc 64MHz
Autres :
DS18B20_2024.h, OneWire_2023.h
LCD_4bits_I2C_2024-01, UART1_Functions.h, RTC_DS3231_2023-10.h
A inclure:
Test_all_char_LCD_2023-08.inc ,Affiche_LCD_Repos_2023-1213.inc
MAJ_RTC_Manuelle_2023-1202.inc ,Dialogue_Operateur_PC_via_UART_2023-0905
MENU_10_123456_2024-0309.inc
LCD_chars_Speciaux_2023-0827.h, Eeprom : Eeprom_PIC_2023.h,
Eeprom_PIC_2023-0906.c
Hardware : Carte PCB Chaudiere
Schema: Chaudiere_Schema_V14.0.0.pdf (Kicad)
Compile le Mar 9 2024 a
16:31:02 UTC
avec version XC8 : 2360
00002 00003 # 00004 MENU10.1 CONSIGNES Consigne Cf 19.0C Consigne Ec 15.0C # Sortie CONSIGNES CFT ECO Boucle sur Menu10.2 Menu 10.2 Temp_Mini_Exter # Sortie Temp_Mini_Exter Boucle sur Menu10.3 Menu10.3 Temp_EAU_Chaudiere # Sortie Temp_EAU_Chaudiere Boucle sur Menu10.4 Menu10.4 MENU_Compens_T_Ressentie= 0.0 # Sortie Compens_T_Ressenti Boucle sur Menu10.5 Menu10.5 via SW0 MENU_Temp_Hors_Gel # Sortie Temp_Hors_Gel Boucle sur Menu10.6 --------------------------------------------------- Menu10.6 SW0 Hysteresis Valeurs HYS int,ext,eau en Eeprom AVANT : HYS_int= -1.50 , HYS_ext =-0.50 , HYS_eau=-3.000 ###############.................<------ chaque # correspond à l'appui d'une touche BPx Sauve valeurs HYS-xxx en eeprom +40 Valeurs de travail en cours: HYS_int= -1.50 , HYS_ext =-1.00 , HYS_eau=-4.000 Relecture Eeprom Valeurs HYS int,ext,eau APRES : HYS_int= -1.50 , HYS_ext =-1.00 , HYS_eau=-4.000 Sortie Normale Menu_Hysteresis ------------------------------------------------------ 00005 00006 |
![]() |
Menu 10.7 ......Indice Energetique NGR_cor et
NGR_ind
rev 29/03/2024
voir MENU10_1234567_2024-0327.inc
.............
annulé 06/04/2024.................
Partie Commune Menus 10.x
void Sortie_Menu10(void)
// parametre P=MPas
{
if (TMR0IF == 1)
{
CPrint(" Sortie sur TimeOut Menu_");
CPrint(Menus_SW0[MPas-1]); CRLF1();
Menu=0;
MPas=0;
}
else
{
if(SPas>0)
{
CPrint(" Sortie Normale Menu_");
CPrint(Menus_SW0[MPas-1]); CRLF1();
Menu=0;
MPas=0;
}
if (SPas==0)
{
if (Duree_Appui>1000)
{ MPas=0;
Menu=0;
CPrint(" Retour Menu=0\r\n");
}
else
{
CPrint(" Sortie ");
CPrint(Menus_SW0[MPas-1]); // -1 car liste commmence à
indice 0 !
CRLF1();
MPas=MPas+1;
if (MPas>6) MPas=1;
CPrint(" Boucle sur Menu10.");
PrintChar(MPas+48);
CRLF1();
}
}
}
__delay_ms(100);
Etats_BP=0;
SPas=0;
IOCBF=0;
}
MENUS DIRECTS
Les menus directs SW1 à SW5 , sont appelés par un appui
sur les touches 1 ..à ...5 pendant 1 seconde..
Touche et durée de touche sélectionnée dans le
traitement interruption INT0 RB0.
Ensuite les Menus sont traités en mode Pooling SANS
INTERUPTION
Menus
Directs
if ((Menu<10) && ( Duree_Appui>1000)
&&( Duree_Appui<6000) )
{
if (Etats_BP==SW0) Menu=0; // sortie Menus directs
if (Etats_BP==SW1) Menu=1; // SW1=2 forçage mode
chauffage Cf ou EC (Confort ou Economique)
if (Etats_BP==SW2) Menu=2; // SW2=4 incr consigne (Modif
consigne en cours temporaire)
if (Etats_BP==SW3) Menu=3; // SW3=8 dec consigne (Modif
consigne en cours temporaire)
if (Etats_BP==SW4) Menu=4; //
SW4=16 Affectation plages semi-horaires préprogrammées ET
modif.programmes Horaires
if (Etats_BP==SW5)
Menu=5; // SW5=32 MAJ RTC
if (Etats_BP==SW12) Menu=6 ;// SW1+SW2=6 bascule mode
Normal ou HORS GEL (consigne 10°C)
//if (Etats_BP==SW31) Menu=7; // SW1+SW3 =10
}
Menu direct SW4
Menu direct appelé via Appui su BP SW4 , pendant > 1sec
Ce menu comporte un
aiguillage ves 2 options
option 1 : Modif. Program
option 2; Affectation au jour de semaine
gestion des BP ....via interruptions !
Code de la partie Aiguillage
exemple d'execution ( ... sur YAT terminal)
choix via SW0, validation via SW1
SW4 a) Affectation
Programme au Jour de semaine
SW4 b) Modification du
programme selectionné
Menu direct SW5 :
MAJ RTC (Real Time Clock)
( LCD et BP en mode pooling)
Menu appelé via appui sur BP SW5 pendant > 1 sec
Une fois entré dans le Menu SW5, ................les BP
sont traités en mode pooling
Le Test consite à imposer une Date , Heure et jour de la
semaine correcte dans la RTC
afin de pouvoir modifer les parametres via un menu
affiché sur le LCD 4x20
Nota :
Avec une RTC neuve
sans pile
A la toute premiere mise sous tension tous les registres
sont à 0
soit year=00 month=00 day=00 js=01=mardi, 00H00M00SS.
Elle doit, ensuite,
toujours etre initialisée avec des données
vraissemblable ( data en BCD !)
Rappel ( issu de la
datasheet RTC3231)
--------------------------------------------------------------------------
The RTC maintains seconds, minutes, hours,
day, date,month, and year information. (calendrier perpetuel inclus )
The date at the end of the month is automatically
adjusted for months with fewer than 31 days, including
corrections for leap year.
The clock operates in either the 24-hour or 12-hour
format with an AM/PM indicator. (On
utilise ici, le format 24H00)
Two programmable time-of-day alarms ( Non utilisées ! )
and a programmable square-wave output are provided. ( sortie 1Hz utilisée pour Led
et Alarme)
Address (0x68)
and data are transferred serially through an I2C
bidirectional bus. (I2C1
Hardware)
The day-of-week register increments at midnight. (variable jS)
Values that correspond to the day of week
are user-defined
but must be sequential (i.e., if 1 equals Sunday, then 2
equals Monday, and so on).
Illogical time and date entries result in undefined
operation
------------------------------------------------------------------------------
il faut donc
initialiser manuellement jS : (aux USA jS=1=Dimanche , en
France jS=1=Lundi)
que si on change la date , pas besoin si on ne modifie
que l'heure et mn ( en supposant qu'elle soit déja
correcte)
mais à eviter si c'est 23H59MN59S !
En ligne #2 du LCD ,
affichage modele de représentation des 6
registres RTC
Chaque registre 8 bits avec 2 caracteres ascii ,
represente Dizaine et unité
LCD_Write_CText_At(2,l,"modele
AAMMJJxSHHMN ");
en correspondance directe de l'init forcée RTC :
tmp[0]=0x00; //start
Oscillateur
tmp[1]=0x01; //second
tmp[2]=0x58; //write min MN
tmp[3]=0x11; //write hour HH;
tmp[4]=0x05; ///write day of week jS
tmp[5]=0x14; // write date JJ
tmp[6]=0x09; // write month MM
tmp[7]=0x23; // write year AA
tmp[8]=0x00;
p1=&tmp[0];
I2C1_WriteNBytes(DS3231_ADDR,p1,8);
En ligne #3 du LCD,
Affiche la date et heure des registres RTC ( mais Non réactualisée!)
,puisqu'on veut la modifier
On entre dans un menu direct via une interruption , mais
ensuite ,
à l'interieur du menu l'interrupt INT0 est desactivée.
if
(Menu==5) // SW5
{
IOCBF=0;
PIR1bits.INT0IF=0;
PIE1bits.INT0IE=0;
sprintf(CRam1," SW5 Menu=%2d MAJ horloge RTC \r\n",Menu);
Print(CRam1);
MAJ_RTC_Manuelle();
// Print(CRam1);
Menu=0;
Etats_BP=0;
Drapeaux.Key_ON=0;
PIR1bits.INT0IF=0;
PIE1bits.INT0IE=1;
}
les switches sont scrutés en mode pooling
!
Le timer0 est utilisé pour sortir sur timeout 10 sec ,si
aucun appui sur BP ( BP=switch)
chaque appui sur un switch SWx
relance le TimeOut
Déplacement transversal
sur la ligne 3 du LCD,
limites : Mini =position colonne=8 ..jusqu'à la position
maxi =colonne 19 ...
Deplacement à gauche via SW0
arrivé en bout (position mini=8) ...si on continue,
retour en Position finale 19 .
Deplacement à droite via SW1
arrivé en bout (position maxi=19) ...si
on continue, retour en Position debut=8 .
le digit concerné clignote avec le
caractere Noir
On peut alors modifier la
valeur (ascii) ciblée:
Increment via SW3
Decrement via SW4
La ligne #3 est donc modifiée en temps reel ..
limites imposées sur chaque valeur ASCII , mais pas d'interaction
de verrouillage entre les digits .
c'est à l'operateur de ne pas mettre n'importe quoi ..
* exception pour le jour de
la semaine .jS .pas de dizaine => pas de
modif possible sur la dizaine
jS est limité entre 1 et 7
le 1 correpond à Lundi ... le 7=dimanche
Si on
rencontre un TimeOut , on sort et tout est annulé !
message "sortie sur timeout
"
Apres toutes les modifs requises,
Validation par SW5 appuyé pendant > 2
sec
le contenu de la ligne #3 , sert de buffer pour recuperer
les valeurs à transmettre à la RTC
mais il faut transcoder l' affiche de couple de caractere
Ascii ,en un Byte au format BCD
pour cela, la fonction qui va bien:
unsigned char
Ascii_Paire_To_BCD( unsigned char *px)
{ unsigned char cd, cu,cx;
cd=*(px)-48;
cx=cd<<4;
cu=*(px+1)-48;
cx=cx+cu ;
return (cx);
}
le LCD en ligne 3 affiche le contenu de la table : Contenu_Ligne_LCD_En_Cours,
un pointeur sur cette table est transmis à la fonction
Ascii_Paire_To_BCD
qui évolue de paire en paire , tout au long de cette
table ...qui contient 12 caracteres -> representant
les 6 registres RTC
la table tmp[] se remplit donc avec les nouvelles valeurs
de registres
qu'on envoie suite dans la RTC en I2C, si validation par
SW5 >2sec
Le LCD affiche alors Sauvegarde
dans RTC
Run sur terminal YAT :
Init RTC Forcee pour ce
test a Vendr 14/09/2023 11:58:01
14/09/23 11H58M01S
Test mode Pooling des 6 BP sur PORTB , de gauche à
droite
Etat initial : k= 127 soit 0x007F m= 127 soit 0x007F
Sorti de test par validation par SW5>2 sec ou Timeout
de 10sec
Bp= 0x02, Duree = 147
Bp= 0x02, Duree = 6
Bp= 0x02, Duree = 89
.. etc ......
Bp= 0x08, Duree = 128
Bp= 0x08, Duree = 103
Bp= 0x20, Duree = 2199......................................................
SW5> 2sec = Validation !
Contenu Ligne #3 LCD :modify 230918011058
px : 23 i= 7 offset j= 0 tmp[ 7]=23
px : 09 i= 6 offset j= 2 tmp[ 6]=09
px : 18 i= 5 offset j= 4 tmp[ 5]=18
px : 01 i= 4 offset j= 6 tmp[ 4]=01
px : 10 i= 3 offset j= 8 tmp[ 3]=10
px : 58 i= 2 offset j=10 tmp[ 2]=58
new RTC 230918011058
Memo dans RTC
Verif. Nouvelle Date et Heure RTC
Le Lundi 18/09/23 10H58M01S
Nota : l'application de ce menu a permis de déceler un
bug sur l'Affichage LCD Repos ,
ligne 3 et 4 affichage partie programmation Horaire avec
caracteres speciaux LCD
Modif déplacement
horizontal :
-> boucle vers debut si deplacement à droite depuis
la derniere position
<- boucle vers la fin si debut deplacement à gauche
depuis la 1ere position
Modif pour Increment/decrement
valeur
usage mode Roll-Over pour diminuer le nombre d'appui
touche
pour passer de 1 à 9 via 8 appui de touche +,
on fait touche - => passe
de 1 à 9 direct
Exemple d'application :
Ordinogramme détaillé :
Chaudiere_MAJ_RTC_Manuelle_2023-1203_Drawio.pdf
Chaudiere_MAJ_RTC_Manuelle_2023-1203.drawio
Menu Direct 8 (Sw3+Sw2)
RAZ Alarmes
rappel Hardware :
#define Alarm_Out LATCbits.LATC0
#define Alarm_Inp1 PORTCbits.RC1
#define Alarm_Inp2 PORTCbits.RC2
#define BP_Egalisation PORTCbits.RC5
#define Alarm_Inp1_dir TRISCbits.TRISC1
#define Alarm_Inp2_dir TRISCbits.TRISC2
#define Alarm_Out_dir TRISCbits.TRISC0
#define BP_Egalisation_Dir TRISCbits.TRISC5
dans init Hardware
RC0PPS =0;
RC1PPS =0;
RC2PPS =0;
RC5PPS=0; // SW6 input
Alarm_Inp1_dir=1; //RC1
Alarm_Inp2_dir=1; //RC2
Alarm_Out_dir=0; // RC0
Alarm_Out=1;
BP_Egalisation_Dir=1; //RC5
dans traitement interruption
:
// detection Entrees dans Menus directs
if (Etats_BP==SW1) Menu=1; // SW1(2) mode Cf ou EC
if (Etats_BP==SW2) Menu=2; // SW2(4) incr consigne
if (Etats_BP==SW3) Menu=3; // SW3(8) dec consigne
if (Etats_BP==SW4) Menu=4; // SW4(16) Affectation
programme ou modif programme
if (Etats_BP==SW5) Menu=5; // SW5(32)
if (Etats_BP==SW12) Menu=6 ;// SW1+SW2=2+4=6 Arret Total
if (Etats_BP==SW31) Menu=7; // SW1+SW3 =2+8=10 bascule
consigne Hors gel ou Normal
if (Etats_BP==SW32) Menu=8; // SW2+SW3 =4+8=12 RAZ
alarmes
dans la boucle
principale du main
if(Menu==8) //SW3+SW2
{ //................... pas encore testé !
CPrint("Reset Alarmes \r\n");
LCD_Write_CText_At(1,1," Reset Alarmes ");
sprintf(CRam1," ALarm1=x ALarm2=x", (Alarm_Inp1>>1)+48,(Alarm_Inp2>>2)+48);
LCD_Write_Text_At(2,1,CRam1);
__delay_xSec(3);
Alarm_Out=1; //stop alarme
Terminaison_Menu_Direct();
}