[C] Programme aquisition capteur dans PIC18F4620.

Fermé
Cotton - 14 avril 2013 à 16:06
 Utilisateur anonyme - 16 avril 2013 à 21:33
Bonjour à tous et à toutes,

Je voulais savoir si le programme proposé plus bas est correct pour l'instant. Je tiens a dire que je n'ai aucunes connaissances en langage C et que je fais mes débuts depuis une semaine.
Je dois acquérir une tension sortant d'un capteur de pression et la numériser pour ensuite pouvoir l'exploiter. La pression devra être affichée sur un écran digital en ASCII donc.
L'acquisition et le traitement du signal du capteur ce fait via un PIC18F4620 ( http://ww1.microchip.com/downloads/en/devicedoc/39626b.pdf ).
J'ai donc commencé par configurer le CAN.


////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

#include <18f4620.h>
#include <stdio.h>
#include <stdlib.h>

//////////////////// Initialisation du CAN /////////////////////

void init_can(void)
{
TRISAbits.AN0 = 1;
ADCON0 = 0b00000011; // conversion registre ADCON0
ADCON1 = 0b00001101; // conversion registre ADCON1
ADCON2 = 0b10******; // conversion registre ADCON2
}

/////////////////// Programme CAN /////////////////////////////

void main(void)
{
while(1)
ADCON0bits.GO = 1; // début conversion A/D
while (ADCON0bits.go == 1); // attendre la fin de la conversion
return (ADRES); // retour du résultat stocké
}

////////////////// Programme Pression ////////////////////////

int main
{
int pression_atm_in = ADRES;
int pression_atm_out = 0;
pression_atm_out = ((1076*pression_atm_in)/1000);
return (ADRES);
}

De plus, il me semple que le PIC ne peut faire le calcul "pression_atm_out = ((1076*pression_atm_in)/1000);". Trop complexe pour lui le pauvre.
Malheuresement, je ne sais pas comment faire pour contourner ce problème. On m'a parlé des tableaux de correspondances en langage C, mais j'y connais rien.

Merci d'éclairer ma lanterne :).

14 réponses

Personne ?
0
Utilisateur anonyme
14 avril 2013 à 18:53
Bonjour

Beaucoup d'erreurs a priori.

1 - Tu as défini deux fonctions 'main'. Ça m'étonnerait que le compilateur ne te signale pas d'erreur. Je suppose que la seconde est le 'vrai' main et qu'elle devrait appeler la première, mais même en supposant ça, il reste un tas de choses bizarres.
On reprend à partir du début

2 - Tu as écrit une fonction init_can. C'est une bonne idée, mais à quoi ça sert si tu ne l'appelles nulle part ?

3 - ADCON0 = 0b00000011; : Cette ligne (et les autres de même allure) me semble suspecte. Ça dépend de comment est défini exactement ADCON0, mais si c'est comme je le pense une simple adresse de registre, il faut sûrement plutôt écrire
* ADCON0 = 0b00000011;


4 - ADCON2 = 0b10******; Des astérisque dans une constante binaire ? Une extension Microchip, peut-être, mais j'ai des doutes.

5 - void main(void) : Si c'est vraiment une fonction qui doit retourner une valeur, elle ne devrait pas être de type void ni s'appeler main

6 -
while(1) 
ADCON0bits.GO = 1; // début conversion A/D 

Pourquoi un while (1) ici ? Ça te crée un boucle infinie, si tu rentres ici tu passeras ta vie à relancer des conversions sans jamais rien faire d'autre.

7 - int main : Si c'est le vrai main, elle devrait être de type void (à vérifier avec le manuel de ton compilateur, mais il y a de grandes chances) et dans tous les cas, il devrait y avoir des parenthèses () à la déclaration de la fonction.
De plus, le corps de la fonction devrait être une boucle infinie car sinon il va faire quoi ton microcontrôleur ? Ce n'est pas la même chose qu'une application qui tourne sous un système d'exploitation et qui rend la main à cet OS quand il a fini. Le plus souvent, dans un microcontrôleur, ton programme est seul et ne rend la main à personne, il doit toujours faire quelque chose.

On parlera du reste quand tout ça sera vu ;-)
0
Merci de ta réponse.

3 - ADCON0 = 0b00000011; : Cette ligne (et les autres de même allure) me semble suspecte. Ça dépend de comment est défini exactement ADCON0, mais si c'est comme je le pense une simple adresse de registre, il faut sûrement plutôt écrire
* ADCON0 = 0b00000011;


Cette ligne me permet de configurer les "paramètres" du convertisseur analogique numérique du PIC18F4620. C'est un registre définie par la doc constructeur. Il me permet de choisir l'entrée analogique à convertir.

4 - ADCON2 = 0b10******; Des astérisque dans une constante binaire ? Une extension Microchip, peut-être, mais j'ai des doutes.


Celui de registre me permet de configurer l'horloge du CAN. Je dois me renseigner avec un ami pour savoir qu'elle valeur mettre.


Pourrais-tu me renvoyer le programme après correction des erreurs principales stp ? Moi qui pensais que je n'avais pas autant de faute, j'ai bien peur d'en refaire 'autres :).

Merci de ta réponse.
0
Utilisateur anonyme
14 avril 2013 à 23:23
3 - Je sais bien que tu cherches à configurer le CNA, et je connais bien les registres. Je ne parle pas de ça mais de la façon dont ton compilateur définit ADCON0, car selon la façon dont il est défini, l'affectation s'écrit d'une manières ou d'une autre : ce n'est pas une question de connaissance des PIC, c'est une question de syntaxe du langage C.
J'ai l'habitude de programmer les PICs en assembleur et ADCON0 est défini comme une constante égale à l'adresse du registre. Si c'est aussi le cas en C comme je le suppose, écrire ADCON0=0b00000011; est illégal et ne veut rien dire. Mais si ADCON0 est défini comme un char *, pas de problème.

4 - le chapitre 19 de la datasheet du 18f4620 explique avec beaucoup de détails comment calculer les valeurs à mettre dans ce registre.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Cela m'étonne pour le registre ADCON0.

Tu dis que tu as une certaines expériences sur le PIC. Est-ce que un PIC est capable de faire le calcul écrit plus haut. Par exemple, une fois convertie en numérique, une tension analogique de de 5V, j'ai en sortie une valeur de 1022 en décimal. Puisque pour 5V je veux avoir 1100 hPa sur un affichage J'ai donc fais une ligne de calcul banale pression_atm_out = ((1076*pression_atm_in)/1000); . Il me semble que le PIC ne peut pas exécuter cette opération complexe pour lui. Comment puis-je faire ?
0
Utilisateur anonyme
15 avril 2013 à 08:35
J'ai été trop méfiant en ce qui concerne ton écriture avec ADCON0. J'ai regardé chez Microchip et en effet, les registres sont bien déclarés de manière à être utilisés comme des simples variables, comme tu l'as fait. Donc oublie ma remarque 3.

Le PIC est capable de faire ton opération et même beaucoup, beaucoup plus compliqué. Le problème, c'est que tu fais ton opération avec des int et les int sont, pour le compilateur Microchip, des nombres de 16 bits, c'est à dire de -32768 à 32767. Donc dès que tu multiplies 1076 par 1022, il y a un dépassement de capacité.
Le remède est très simple, il faut travailler avec d'autres types de variables.Regarde au chapitre 2 du "MPLAB C18 C compiler user's guide" (si c'est bien la suite C18 que tu utilises) tu verras les différents types et tu pourras choisir le plus adapté à tes besoins. même un type réel si nécessaire.
0
Ok merci pour ces infos.
Je vais faire ça et je renvois le programme corrigé par mes soins, en espérant que je vais pas en rajouter, des fautes.

EDIT:

A oui, et aussi, après la conversion, je peux récupérer du décimal directement ou c'est du binaire naturel que je dois ensuite convertir via un sous programme ?

Merci
0
Utilisateur anonyme
15 avril 2013 à 11:42
après la conversion,
Si tu parles de la conversion analogique/numérique, oui c'est bien du binaire naturel, mais ce n'est pas ce nombre-là que tu veux afficher en principe.
Si tu parles du résultat de calcul après mise à l'échelle, ce sera encore du binaire naturel, ou un nombre à virgule flottante, ça dépend de tes choix pour calculer la formule.
Dans tous les cas, le compilateur est fourni avec des bibliothèques de fonctions pour traduire ces variables en chaines ASCII lisibles par un humain. Il restera l'étape de l'envoi de cette chaîne vers un afficheur, qui n'apparaît pas du tout dans ton programme pour l'instant.
0
Exact, pour tout dire je suis dans un projet de conception ne station météo. L'affichage est géré par d'autres personne de mon groupe. Je n'ai qu'a envoyé la donnée et eux se débrouillent comme ils peuvent avec.

Je parle bien d'après la conversion A/N. Si c'est bien du binaire naturel, comment faire pour ensuite retrouver, sur un affichage la "bonne valeur" de pression ?
Je pensais, très simplement, que je pouvais recevoir une valeur décimale, donc pour un exemple 1022 pour une pression de 1100 hPa (si on suit le quantum) que je pouvais utiliser ensuite pour faire un calcul pour retrouver une valeur de 1100 sur un affichage.
0
Utilisateur anonyme
15 avril 2013 à 13:34
Tout est une question d'interface avec l'équipe qui gère l'affichage : attendent-ils un nombre ou une chaîne de caractères ?
Si c'est un nombre, tu as juste ta formule à appliquer (correctement, c'est à dire en tenant compte de la taille des variables comme je te l'ai dit plus haut) et c'est tout.
Si c'est une chaîne de caractères, la conversion se fait facilement avec sprintf.
0
sprintf nécessite pas d'avoir une donnée en ASCII ?

Nous disposons d'afficheur 7 segments basiques.
0
Utilisateur anonyme
15 avril 2013 à 23:32
sprintf nécessite pas d'avoir une donnée en ASCII ?
Non, c'est le contraire : sprintf permet d'obtenir de l'ASCII à partir d'une (ou plusieurs) variable.

Vous avez des afficheurs 7 segments, tout dépend de leur interface. Mais tu as dit que l'affichage était géré par d'autres personnes : ce n'est pas ton problème. Par contre, tu dois savoir quelle interface tu as avec ces personnes. Dire "Je n'ai qu'a envoyé la donnée", c'est de la littérature, pas de la technique. Il faut préciser exactement sous quelle forme cette donnée est envoyée.
0
Il me semble qu'il me faut l'envoyer sous format ASCII.
0
Utilisateur anonyme
16 avril 2013 à 21:33
Il me semble
Ça ne suffit pas, il faut savoir.
Pour un afficheur 7 segments, à mon humble avis, ce n'est pas l'interface la mieux adaptée puisque l'afficheur 7 segments ne peut pas afficher la plupart des caractères ASCII.
Pas grave de toutes manières, puisqu'on passe d'une valeur numérique à l'ASCII en une seule et unique ligne avec un sprintf.
0