Dans le cadre d’un projet industriel, les étudiant doivent piloter en tout ou rien sous 230V un signal lumineux (ampoule), un signal sonore (sirène), un moteur pour l’aspiration de fumées, un régulateur de vitesse pour un convoyeur (altivar) et des régulateurs PID (eurotherm), le tout sur bus physique RS485 avec le protocole ModBUS. Malheureusement l’altivar n’est plus produit et la carte de commande sur bus RS485 n’est donc plus produite non plus. L’entrepreneur ne souhaite pas changer son altivar. Il reste donc l’entrée 0-10V pour donner la consigne de vitesse. Il faut donc générer une tension continue variable et pilotable par bus RS485 et compatible ModBUS. Plutôt que de faire un assemblage de « différents morceaux », j’ai réalisé une carte électronique qui suit ce cahier des charges.
Réalisation de la carte électronique
Cette carte électronique doit donc répondre au cahier des charges suivant:
- piloter en tout ou rien trois sorties 230V (voyant lumineux, alarme sonore, aspirateur à fumées)
- générer une tension continue variable comprise entre 0V et 10V pour la consigne de vitesse de l’altivar
- être compatible avec les régulateurs de températures qui fonctionnent sur bus RS485 avec le protocole ModBUS en mode RTU
- permettre de piloter la consigne de l’altivar de manière manuel (avec un potentiomètre multitours) ou automatique (par la tension générer sur la carte)
- fonctionner à partir d’une tension unique régulée de 5V
Ce qui m’a conduit à adopter les solutions suivantes pour un prototype en fonction de ce que j’avais comme composants disponibles :
- la réception de la trame ModBUS, son décodage et enfin le pilotage de l’ensemble sera réalisé par un microcontrolleur Microchip PIC18F2520
- pour piloter en tout ou rien du 230V, j’ai utilisé des relais classiques 12V/230V 1A
- le bus RS485 deux fils sera piloté avec un CI du type DS75176
- le 12V de commande des relais sera réalisé à partir du 5V à l’aide un convertisseur de type « boost » piloté par le PIC
- la consigne 0-10V sera réalisé par filtrage d’un signal MLI généré par le PIC puis amplifié (x2) par un montage à amplificateur opérationnel. Cet amplificateur utilisant le 12V comme tension d’alimentation
- l’aiguillage de la tension continue générée par le PIC (mode automatique) ou celle issu du potentiomètre (mode manuel) sera réalisé par un relai
Ce qui nous mène au schéma électrique suivant (le fichier original au format Proteus Isis 7.4 est disponible en fin d’article) :
Quelques explications sur ce schéma :
- la carte est alimentée par une alimentation extérieure industrielle régulée 5V. La diode D1 protège le montage contre les inversions de polarité. Cependant elle introduit un problème : en effet la chute de tension dans cette diode est proportionnelle au courant qui la traverse. Lorsque les relais sont alimentés, le « 5V » varie ! Or le CAN du PIC utilise comme référence cette tension de 5V ainsi que la génération du signal 0-10V. Je pense donc qu’à terme il faudra soit supprimer cette diode, soit alimenter la carte en 24V continu et générer les tensions continues de 5V et 12V (ce qui supprimera le convertisseur boost). C3 et C4 sont des condensateurs de filtrage.
- la conversion du signal RS485 en signal RS232 TTL est assuré par un ci du type SN75176. Comme on utilise un bus RS485 sur 2 fils, cela sous entend que l’on fonctionne en mode half-duplex. Il faut donc gérer ce mode en pilotant les lignes DE et RE. En mode réception, il faut mettre un état bas sur les lignes 2 et 3. En mode émission il faut mettre un état haut. Cette gestion est assurée de manière automatique dans le code C du PIC. R6 et R7 protège les entrées du SN75176. R8 et J2 permettent de « fermer » le bus RS485 sur une impédance de 120 Ohms pour éviter les réflexions en bout de ligne. R9 et J3 permettent de réaliser un « pull-up » de la ligne A du bus RS485. R10 et J4 assurent le « pull-down » de la ligne B du bus RS485.
- Les composants autour des relais RL1, RL2 et RL3 permettent de piloter en tout ou rien ces relais. Les DELs permettent de visualiser que les relais sont en position « travail ». En effet si la carte ne fonctionne pas ou en absence d’alimentation les relais sont sur leur position repos (donc pas de voyant lumineux allumé, pas de sirène mais pas d’aspirateur à fumées non plus). Comme les contacts « travail » et « repos » sont sortis sur des borniers, c’est l’utilisateur qui choisira sa configuration.
- le convertisseur « boost » est réalisé autour des composants Q5, D7, BOB et C1. Le transistor mosfet utilisé ici est surdimensionné mais c’est celui que j’avais de disponible. Attention à prendre une diode rapide pour D7 (et pas une 1N4007 comme indiqué sur le schéma). R22 protège la grille du transistor et R23 bloque le transistor en l’absence de commande. Le pont diviseur R20/R21 permet de renvoyer vers le PIC une image de la tension de sortie. Le système fonctionne alors en boucle fermée et l’asservissement est réalisé par le PIC. En effet, en gros, il faut piloter le rapport cyclique du signal MLI PWM_12V pour obtenir un 12V continu quelque soit le courant demandé par les relais. Cette partie disparaitra si je choisi d’alimenter la carte en 24V. Cette partie était surtout là pour me faire plaisir et tester un montage que je n’avais pas encore utilisé 🙂 mais du coup comme le système est pleinement fonctionnel je l’utiliserais dans d’autres montages.
- l’amplificateur U3 sera du type « rail to rail » (pas de tensions de déchets) pour gérer les tensions basses en particulier. Les tensions hautes prés du 10V posant moins de problèmes car l’amplificateur est alimenté en 12V. R14 et C6 filtrent le signal MLI issu du PIC pour obtenir une tension continue comprise entre 0V et 5V. U3, monté en amplificateur non inverseur, multiplie cette tension par deux (gain fixé par R11, R12) pour obtenir la gamme 0-10V. D5 protège l’entrée de l’altivar contre les tensions supérieures à 10V. R13 et C7 filtrent l’alimentation de U3.
- le relais RL4 permet de commuter entre la tension fournie par un potentiomètre extérieur (P1) et la tension issu de U3 pour réaliser la tension de consigne de l’altivar. Ce relai assure donc la commutation entre le mode automatique et le mode manuel.
- enfin le microcontroleur U1 assure la gestion de l’ensemble. J1 est le connecteur de programmation. J7 permet de choisir la vitesse du bus rs485 (9600 ou 19200). J5 et J6 permettent de choisir l’adresse de la carte sur le bus RS485 (adresse 16, 32, 64 ou 128). Un tableau récapitulatif de ces cavaliers sera présenté plus loin dans cet article.
On passe à la phase de routage sur une carte au format « europe », on câble et on obtient la carte suivante:
Étude du protocole ModBUS sur liaison physique RS485 en mode RTU
Le protocole ModBUS est décrit sur différents sites : wikipédia, stielec
La liaison physique RS485 est décrite sur : wikipédia, technologuepro
Mais je me suis principalement appuyé sur le document officiel : Modbus Serial Line Protocol and Implementation Guide
La liaison physique RS485 permet des liaisons multipoints, on peut donc connecter plusieurs esclaves et un maitre sur le même bus. Dans notre cas, le maitre sera un système embarqué sous GNU/Linux avec un adaptateur RS232/RS485 et les esclaves seront les régulateurs de températures eurotherm et la carte d’E/S. Chaque esclave doit avoir une adresse unique sur le bus (1 à 247). L’adresse 0 étant une adresse de diffusion (ou broadcast), les adresses supérieures à 247 sont réservés.
Il existe deux mode de transmission du protocole ModBUS sur voie série : le mode ASCII et le mode RTU (Remote Terminal Unit). Les régulateurs de température fonctionnant en mode RTU, on choisit donc d’implémenter ce mode pour la carte E/S. Le format de transmission en mode RTU pour chaque octet est le suivant :
- un bit de start (front descendant)
- 8 bits de données : poids faible en premier
- 1 bit de parité (la norme recommande une parité paire mais nous n’utiliserons pas de parité car les régulateurs sont configurés de cette manière)
- 1 bit de stop s’il y a un bit de parité sinon 2 bits de stop (dans notre montage : pas de bit de parité et un bit de stop)
Le format d’une trame ModBUS RTU est le suivant:
- Adresse de l’esclave sur un octet compris entre 1 et 247.
- Le code fonction correspond à une opération demandée par le maitre auquel l’esclave doit répondre sauf dans le cas ou le maitre envoie une trame de broadcast (à l’adresse 0).
- Les données que ce soit pour une demande de la part du maitre ou une réponse de l’esclave sont groupés sous forme de mots (2 octets) dont le MSB est en premier.
- Le CRC est un code de vérification de la trame généré par le maitre ou l’esclave. Ce CRC suit la norme CRC16 : l’algorithme est décrit dans le document officiel de la norme. Une application en ligne pour calculer les CRC est disponible ici ou là.
Chaque trame ModBUS RTU doit être précédé et suivi d’un temps de repos de 3,5 fois la durée d’un caractère (d’un octet). Ce qui donne au niveau temps : à 9600 bauds/s : 4ms et à 19200 bauds/s : 2ms pour des trames 8E1. La détection de fin de trame sur le PIC se fera en détectant ce temps après la réception du dernier caractère.
Le ModBUS propose un ensemble de fonctions (Code Fonction). Toutes ces fonctions lisent ou écrivent dans une zone mémoire spéciale de l’esclave pour commander les différents organes de la carte. Dans notre cas le découpage mémoire des registres internes est le suivant:
- Registre 0 sur 16 bits : pilote le relais 1. Écrire un ‘0’ dans ce registre met le relai en position repos, écrire un chiffre supérieur à 0 met le relai en position travail (dans notre exemple : alarme visuelle)
- Registre 1 sur 16 bits : pilote le relais 2. Écrire un ‘0’ dans ce registre met le relai en position repos, écrire un chiffre supérieur à 0 met le relai en position travail (dans notre exemple : alarme sonore)
- Registre 2 sur 16 bits : pilote le relais 3. Écrire un ‘0’ dans ce registre met le relai en position repos, écrire un chiffre supérieur à 0 met le relai en position travail (dans notre exemple : pilote l’aspirateur des fumées)
- Registre 3 sur 16 bits : pilote le relais 4. Écrire un ‘0’ dans ce registre met le relai en position repos, écrire un chiffre supérieur à 0 met le relai en position travail (dans notre exemple : permet de basculer du mode manuel (position repos) au mode automatique (position travail))
- Registre 4 sur 16 bits : génère une tension continue comprise entre 0V et 10V. Écrire un ‘0’ dans ce registre génère du 0V en sortie, écrire ‘1023’ génère du +10V (dans notre exemple, cette tension sert au pilotage du régulateur de vitesse Altivar)
Dans notre cas, la carte d’E/S ne répondra qu’à trois commandes:
- Code fonction 0x03 : Read Holding Registers : Lire les registres internes. Cette commande permet d’obtenir l’état des différents organes de la carte. Cette commande permet de lire n registres 16 bits à partir du registre x codé sur 16 bits.
*: le nombre d’octets renvoyés est égale au Nb de registre à lire x 2
Par exemple la trame ModBUS suivante sans CRC permet de lire l’état des trois premiers relais en une seule lecture (l’esclave est à l’adresse 16 ou 0x10) : 0x10 0x03 0x00 0x00 0x00 0x03. Si vous désirez obtenir la valeur de la tension actuelle qui pilote l’altivar : 0x10 0x03 0x00 0x04 0x00 0x01 - Code fonction 0x06 : Write Single Register : Ecrire dans un registre. Cette commande permet d’écrire une valeur codée sur 16bits dans le registre indiqué.
Vous remarquez que si tout c’est passé correctement la réponse est identique à la requête. Par exemple la trame ModBUS sans CRC qui suit permet de passer le relais2 en mode travail : 0x10 0x06 0x00 0x01 0x00 0x01.
- Code fonction 0x08 : Diagnostics : Diagnostique. Seule la sous fonction 0x0000 est implémenté. Cette sous fonction est « echo ». La réponse est identique à la requête. Par exemple, si vous envoyez la trame suivante sans CRC : 0x10 0x08 0x00 0x00 0x12 0x34, vous devriez obtenir exactement la même chose en retour.
Code source en Langage C pour le PIC18F2520
Le code source suivant permet de réaliser le cahier des charges précédent. Il est commenté, cependant si quelque chose n’était pas assez clair, n’hésitez pas à me contacter…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
// Carte gestion des alarmes, de l'aspirateur de fumées, et de l'altivar // avec le protocole MODBUS sur voie série (ModBUS RTU) RS485 // Projet Four - InnovDecor // O. Dartois - le 19/02/2012 // Remarque: Je me suis basé pour implémenter le protocole ModBUS sur la doc // des régulateurs 2208e de la société EuroTherm. Dans la présentation des trames // il y a une erreur sur l'ordre des octets du CRC. Dans la documentation il est // indiqué MSB puis LSB or aprés lecture du protocole officiel: // http://www.modbus.org/docs/Modbus_over_serial_line_V1_02.pdf p44 // il s'avère que l'on doit transmettre dans l'ordre LSB puis MSB !!! // Seulement 3 fonctions du protocole MODBUS sont implémentées dans ce code // et pour les besoins du projet. Un mot = 16 bits // Fonction 06 : Ecriture d'un mot // Fonction 03 : Lecture de N mots // Fonction 08 : Bouclage (ou loopback) //#include <16F886.h> #include <18F2520.h> #device *=16 #device adc=10 // CAN en mode 10bits #FUSES NOWDT //No Watch Dog Timer #FUSES INTRC_IO //Oscillateur interne si utilisé //#FUSES HS //Utilisation d'un quartz externe >= à 4MHz #FUSES PUT //Power Up Timer #FUSES MCLR //Master Clear pin enabled #FUSES NOPROTECT //Code not protected from reading #FUSES NOCPD //No EE protection #FUSES NOBROWNOUT //No brownout reset #FUSES NOIESO //Internal External Switch Over mode enabled #FUSES NOFCMEN //Fail-safe clock monitor enabled #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #FUSES NODEBUG //No Debug mode for ICD #FUSES NOWRT //Program memory not write protected //#FUSES BORV21 //Brownout reset at 2.1V #FUSES CCP2B3 // Sortie de la PWM2 sur la broche B3 // Horloge interne a 8MHz //#use delay(internal=4M, clock=16M) #use delay(internal=8M) // Activation du SCI à 9600 bauds/s en 8N1, gestion du half duplex avec la broche C5 #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ENABLE=PIN_C5) // Gestion par le programmeur des ports d'E/S #use fast_io(A) #use fast_io(B) #use fast_io(C) // Define pour faciliter la lecture du programme #define AL1 PIN_A1 #define AL2 PIN_A2 #define AL3 PIN_A3 #define MAUTO PIN_A4 #define GEST_HALF PIN_C5 #define AL1_ON output_high(AL1) #define AL1_OFF output_low(AL1) #define AL2_ON output_high(AL2) #define AL2_OFF output_low(AL2) #define AL3_ON output_high(AL3) #define AL3_OFF output_low(AL3) #define MAUTO_ON output_high(MAUTO) #define MAUTO_OFF output_low(MAUTO) #define CHOIX_VITESSE input(PIN_B2) #define MODBUS_LECTURE 0x03 #define MODBUS_ECRITURE 0x06 #define MODBUS_BOUCLAGE 0x08 // Les deux lignes suivantes ne sont plus nécessaires car c'est gérer par le #use RS232 //#define EMISSION output_high(GEST_HALF) //#define RECEPTION output_low(GEST_HALF) // Variables globales du programme const float consigne=12.0; int8 addr_carte = 16; volatile int8 req_modbus[16], cpt_req_modbus=0; volatile int1 recep_trame_modbus = false; // Cette structure permet d'avoir l'état des differentes E/S de la carte // toutes les variables sont en int16 pour être conforme avec le MODBus struct registres_interne { int16 relai0; int16 relai1; int16 relai2; int16 relai_ma; int16 val_cons10V; } registres_carte; // Routines d'interruptions // Interruption réception voie serie #int_RDA void RDA_isr(void) { // On stocke le caractère recu dans le tableau d'octets req_modus puis // on incremente le compteur de réception req_modbus[cpt_req_modbus] = getchar(); cpt_req_modbus++; // Le timer0 gère le timeout, à chaque réception de caractères on repart à 0 // On met le compteur du timer0 à 0 set_timer0(0); // On efface le drapeaux d'interruption car il a été fixé par ailleurs clear_interrupt(INT_TIMER0); // On active l'interruption enable_interrupts(INT_TIMER0); } // Si on recoit rien au bout de 1,5 fois la durée d'un octet on considère que // la trame modbus est complète #INT_TIMER0 void timer0_isr(void) { disable_interrupts(INT_TIMER0); recep_trame_modbus = true; } // Fonction d'initialisation pour parametrer tous les modules du PIC void initialisation(void) { int8 choix_adresse; // Variable temporaire pour le choix de l'adresse de la carte setup_adc_ports(AN0|VSS_VDD); // Activation de l'entree analogique AN0 setup_adc(ADC_CLOCK_INTERNAL); // Utilisation de l'horloge interne du CAN set_tris_a(0b11100001); // On fixe les E/S sur les ports set_tris_b(0b11110111); // 0 : Output = sortie set_tris_c(0b10011011); // 1 : Input = entree port_b_pullups(0b00000111); // Activation des résistances de rappel individuellement setup_spi(SPI_SS_DISABLED); // Desactivation du SPI setup_timer_0(T0_INTERNAL|T0_DIV_32|T0_8_BIT); // Reglage du timer 0 setup_timer_1(T1_DISABLED); // Desactivation timer 1 setup_ccp1(CCP_PWM); // Activation de la premiere PWM : generation 12V setup_ccp2(CCP_PWM); // Activation de la deuxieme PWM : generation 10V setup_timer_2(T2_DIV_BY_1,255,1); // Activation des PWM avec le timer2 setup_comparator(NC_NC_NC_NC); // Desactivation des modules de comparaison set_adc_channel(0); // Choix du canal 0 pour le CAN output_a(0); // Sorties du port A a 0 : relais en position repos memset(&registres_carte,0,sizeof(registres_carte)); // Initialisation des registres de la carte à 0 set_pwm1_duty(1); // MLI generation 12V arrêté set_pwm2_duty(registres_carte.val_cons10V); // MLI generation 10V arreté disable_interrupts(INT_TIMER0); // Interruption tts les 1/(8MHz/4) * 32 * 256 = 4,096ms enable_interrupts(INT_RDA); // Activation interruption voie serie enable_interrupts(GLOBAL); // Activation des interruptions (globalement) if (!CHOIX_VITESSE) setup_uart(19200); // Si un cavalier est présent sur J7 on change la vitesse // de l'USART à 19200 bauds/s au lieu de 9600 bauds/s choix_adresse = input_b()&0x03; // On récupère l'état des cavaliers J5 et J6 // Si un cavalier =>0, si pas de cavalier =>1 car résistances de rappel interne switch (choix_adresse) { case 3 : addr_carte = 0x10; break; // Pas de cavalier : adresse de la carte : 0x10 ou 16 case 2 : addr_carte = 0x20; break; // Pas de cavalier sur J6, cavalier sur J5 : adresse de la carte : 0x20 ou 32 case 1 : addr_carte = 0x40; break; // Pas de cavalier sur J5, cavalier sur J6 : adresse de la carte : 0x40 ou 64 case 0 : addr_carte = 0x80; break; // Cavalier sur J5 et J6 : : adresse de la carte : 0x80 ou 128 } } // Code trouvé sur un forum, une version optimisé existe chez CCS int16 calc_crc16() { int16 crc = 0xFFFF; int8 i, done = 0; int8 todo; do { todo = req_modbus[done]; crc ^= todo; for (i = 0; i < 8; i++) { if (crc % 2 != 0) { crc = (crc >> 1) ^ 0xA001; } else { crc = crc >> 1; } } done++; } while (done < (cpt_req_modbus-2)); return crc; } void main() { float val_tension; int16 val_pwm=0; int16 CRC16, registre, donnee; int8 i,j; initialisation(); while(true) { if (recep_trame_modbus) { // On vérifie que l'adresse de l'esclave est la notre et que l'on a recu // plus que 3 octets (taille minimum d'un requete MODBUS : 4 octets) // Ex: Addr Esclave + Fonction Bouclage + CRC (2 octets) = 4 octets if (req_modbus[0] != addr_carte || cpt_req_modbus<4) goto fin; // calcul du CRC16 et comparaison avec celui transmis dans la trame CRC16 = make16(req_modbus[cpt_req_modbus-1], req_modbus[cpt_req_modbus-2]); // on sort si le CRC n'est pas correct if (CRC16 != calc_crc16()) goto fin; // On teste si on gère la fonction demandée if ((req_modbus[1] != MODBUS_BOUCLAGE) && (req_modbus[1] != MODBUS_ECRITURE) && (req_modbus[1] != MODBUS_LECTURE)) goto fin; // on aiguille suivant la fonction choisie switch (req_modbus[1]) { case MODBUS_ECRITURE : // On analyse si le registre existe sinon on sort registre = make16(req_modbus[2], req_modbus[3]); if (registre > 4) goto fin; donnee = make16(req_modbus[4], req_modbus[5]); switch (registre) { case 0 : (donnee)?AL1_ON:AL1_OFF; registres_carte.relai0=donnee; break; case 1 : (donnee)?AL2_ON:AL2_OFF; registres_carte.relai1=donnee; break; case 2 : (donnee)?AL3_ON:AL3_OFF; registres_carte.relai2=donnee; break; case 3 : (donnee)?MAUTO_ON:MAUTO_OFF; registres_carte.relai_ma=donnee; break; case 4 : if (donnee <= 1023) { set_pwm2_duty(donnee); registres_carte.val_cons10V=donnee; } break; } // Notez l'absence du break ici pour renvoyer la réponse case MODBUS_BOUCLAGE : for (i=0; i<cpt_req_modbus; i++) putc(req_modbus[i]); break; case MODBUS_LECTURE : registre = make16(req_modbus[2], req_modbus[3]); if (registre > 4) goto fin; donnee = make16(req_modbus[4], req_modbus[5]); if ((donnee == 0) || (donnee > 5)) goto fin; // on teste si on ne demande pas des registres en dehors de la plage autorisée // on a 5 registres accésibles à partir de 0 if ((registre+donnee) > 5) goto fin; req_modbus[2] = donnee * 2; // Les deux boucles 'for' pour remplir le tableau de la requete modbus à partir de la structure // qui représente la mémoire de registre. Deux boucles pour gérer le passage LSB,MSB de la structure // vers le format modbus qui réclame MSB,LSB for (i=registre*2,j=0;j<donnee*2;i+=2,j+=2) req_modbus[4+j]=*((int8 *)&registres_carte + i); for (i=registre*2,j=0;j<donnee*2;i+=2,j+=2) req_modbus[3+j]=*((int8 *)&registres_carte + i + 1); cpt_req_modbus = 3 + donnee * 2 + 2; CRC16 = calc_crc16(); req_modbus[cpt_req_modbus-1] = CRC16>>8; req_modbus[cpt_req_modbus-2] = CRC16&0x00FF; for (i=0; i<cpt_req_modbus; i++) putc(req_modbus[i]); break; } fin: recep_trame_modbus = false; cpt_req_modbus = 0; } // Boucle d'asservissement de la tension 12V // Pont diviseur : R20=68K, R21=33K donc VCAN_12V = (33K/(33K+68K)*(VCC/2^10) val_tension = read_adc() * 0.0145; if (abs(consigne-val_tension) > 0.05) { if (val_tension<consigne && val_pwm<1000) val_pwm++; if (val_tension>consigne && val_pwm>5) val_pwm--; set_pwm1_duty(val_pwm); } delay_us(500); } } |
Remarque : lorsqu’une trame n’est pas valide ou qu’elle contient une requête non conforme, le code se contente de l’ignorer. Donc si vous ne recevez rien en retour d’une requête c’est que très certainement celle-ci est incorrecte ou que votre liaison physique est défectueuse. Rappelez-vous aussi qu’en l’absence de cavalier sur J5,J6 et J7 la carte a comme adresse 0x10 ou 16 en décimal et qu’elle fonctionne en 8N1 à 9600 bauds/s !
Programmation de la carte en langage C++ et réalisation de classes
Cette carte sera pilotée sous au moins deux environnements : un avec du GNU/Linux (emDebian sur plateforme TQ6410 avec QT comme framework), l’autre avec un PC industriel sous Microsoft Windows. Pour faciliter le pilotage de cette carte et des régulateurs, il a été décidé de créer des classes C++. Ces classes C++ se baseront sur la librairie open source libmodbus disponible sur libmodbus.org. Je ne peux pour l’instant pas donner les codes sources de ces classes, ni les tests unitaires réalisés avec celles-ci tant que les étudiants n’ont pas fini leur projet. La seule chose que je peux affirmer pour l’instant, c’est que les classes fonctionnent dans le cadre que l’on s’est fixé. Les codes sources seront disponibles lorsque les étudiants auront finalisé le projet…
L’interface graphique de test suivante a été réalisé sous GNU/Linux Debian avec Qt4.7 et les classes développées pour la carte :
Conclusion temporaire
Je pense que la mise en place chez l’industriel concerné va amener des modifications au niveau de la carte d’E/S. Lorsque le projet sera totalement finalisé, je mettrais à disposition les sources et le nouveau typon. En attendant vous avez largement de quoi débuter avec cette carte…
Bonjour,
je compte entamer la réalisation de la carte,
mais le schéma est totalement illisible
pourriez vous m’envoyer les fichiers sources, schémas et typons
Merci beaucoup
très bien
Bonjour,
Merci pour toutes les infos, le projet est fini a present?
Ca m’interesse de voir la fin du projet.
bonjour
je suis en train de construire ma maison et je voudrais intégrer un automate programmable industriel de marque saia burgess.
Votre projet de carte m intéresse énormément, notamment par rapport au coût des carte original, mes questions sont les suivantes:
-ou en est votre projet?
-pensais vous qu’il soit possible de faire des carte disposant de 16 entrées ou 16 sortie ?
Merci d’avance
salut.
je travaille dans le domaine agricole et si vous avez des programmateur , je suis à votre disposition. merci