Go Down

Topic: Résolu Boitier E85 avec un Arduino nano (Read 10006 times) previous topic - next topic

marcus_95

Ok merci, j'avance doucement et surement avec le FORUM.

marcus_95

Ma prochaine étape:

sei(); //autorise les interruptions
Détection changement d'état sur une broche du port C ->LOW
Interruption du programme : pcmsk2
* mise en mémoire de la variable volatile de la valeur time2 (time2 = micros();)
* changement d'état de la sortie correspondante
* on sort de l'interruption cli(); //désactive toute interruption

On va en 1


Détection changement d'état sur une broche du port C -> HIGH
Interruption de programme : pcmsk0
* calcule du temps  (time3 = micros() - time2;)
* ajout du temps si nécessaire (time3 + valeur ;)
* changement d'état de la sortie correspondante
* on sort de l'interruption  cli(); //désactive toute interruption

On va en 1


1)   On va s'occupé du lambda, les interruptions sont prioritaires. A écrire en C ou en assembleur.


Le programme doit être bouclé en moins de 500 µs.

Super_Cinci

Ne pas mélanger les INT et PCINT, ce sont deux sources d'interruptions totalement différentes.

Ton exemple est bon pour démarrer, reste à voir si la led est bien câblée, si tu as bien ton bouton poussoir entre PD2 et GND et s'il marche bien.

et enfin : dans ton setup, la ligne "DDRB |= B1000000; // PB5 en sortie", il y a un zéro de trop.

Petite astuce cachée dans la datasheet (comme beaucoup d'autres) : pour faire changer l'état d'une pin configurée en sortie, il suffit d'écrire un 1 dans le bit correspondant du port d'entrée. Dans ton cas, faire "PINB |= 0x20;" ...

Sinon, pour ton système, avec deux ou trois interruptions, tu peux t'en sortir sans avoir besoin de scanner les entrées. En utilisant le timer 1 en PWM one shot, ainsi que l'interruption ICP1 pour lire aisément la durée légale d'injection et calculer ainsi ce que tu veux (si tu dois augmenter de x la durée, alors un simple "OCR1A = ICR1 + x" fera tout le boulot! c'est là que l'interruption PCINT peut te rendre service!

Si des injecteurs se trouvent ouverts en même temps (haut régime, il est possible d'ouvrir l'injecteur avant l'ouverture de la soupape d'admission, c'est ce qu'il se passe sur mon F3N où les 4 injecteurs sont en //, donc giclent 4 fois par cycle), il y aura une petite bidouille à prévoir, mais il est toujours possible de s'en sortir en utilisant un peu de logique externe...

tu mets comme le propose b@too le calcul lambda dans le loop(), comme ça, ça sera calculé en permanence, et les ints n'auront plus qu'à venir chercher la variable contenant la valeur lambda...

Surtout, il faut se dire que si dans le tas, tu n'as pas eu le temps de mettre la durée d'injection à jour et que du coup, de temps en temps, un injecteur ne s'ouvre pas comme tu l'aurais souhaité, ce n'est pas grave, ce n'est pas une erreur de 3 ou 4µs un coup sur mille qui empêchera ton moteur de bien tourner.

Mais je reconnais que ça va te demander quelques exercices avant de pouvoir comprendre tout ça...

Super_Cinci

oublies de suite micros(), ça va prendre trop de temps. regarde de plus près ce que sont capables de faire les timers quand on leur cause en direct...

marcus_95

J'ai bien câblé le 0 en plus c'est pour la broche 6 pas la 5.
Oui c'est plus clair en Hexa.
Pour le reste je suis largué :o
Je ne jette pas l'éponge, je poursuis.

Super_Cinci

Attention aussi, cli() désactive toutes les interruptions (à l'exclusion du RESET), donc si quelque chose d'important se produit, tu ne le verras pas.

Les interruptions doivent gérer tout ce qui doit réagir instantanément. Tout ce qui peut attendre ou qui n'a pas de grosse importance temporelle va dans le loop().

Depuis quelques mois, je réfléchis à fabriquer un calculateur d'allumage (AEI) pour mes vieux moteurs renault. C'est un peu le même système, ou du moins la même démarche. Mais ce qui m'empêche d'aller plus loin que le papier, c'est qu'il faut d'abord que j'arrive à relever la carto actuelle d'un vrai calculateur, donc mettre au point un banc de mesure qui fera tourner un calculateur sur l'établi. Une fois ça fait, je pourrai alors partir sur une bonne base...

J'ai fait pas mal de petits programmes devant gérer des actions en temps réel (sans latence), et en général, je fais la liste de ce que doit faire mon système, puis après, j'affecte les ressources matérielles du proc à chacune de ces actions, tout en vérifiant qu'il n'y a pas d'interférences. Après, ça se programme tout seul...

Tu peux regarder le programme que j'ai fait pour mon carillon (dans projets finis), il n'y a pas beaucoup de commentaires, mais j'utilise les trois timers qui tournent en faisant leurs vies et en déclenchant des int, loop() s'occupe de voir les entrées et met les paramètres à jour. Une fois la mélodie lancée, tout se fait par interruption, sans que loop() n'intervienne, donc loop() peut tout à fait faire autre chose pendant ce temps, alors que la mélodie joue sans a-coups.

marcus_95

Merci pour tes conseils, je vais aller voir pour le carillon. pour une cartographie de 2 a 8 cy j'avais trouver ça:
http://www.alpine.free.fr/

Je ne sais si ça peut aider.

Super_Cinci

Je ne sais si ça peut aider.
Merci, mais les calculateurs que je vise (1,2L à 1,7L) ont des courbes numérotées, et il existe un grand nombre de numéros, même sur deux moteurs identiques, renault n'a pas toujours mis la même carto... Donc pour remplacer un calculateur par mon système, le plus simple des de relever la carto directement...

Mais c'est un autre problème.

Je te souhaite bon courage dans ta découverte de l'arduino vu sous la couette...

marcus_95

Ok je comprends mieux, merci, je poursuis mes investigations pour mon boitier. Bonne soirée.

marcus_95

Bonjour, j'ai commencé à réécrire mon programme basé sur les interruptions, les commutations ce font bien et même plusieurs en même temps.
 Merci de votre aide sans vos conseilles je n'en serais pas là. Maintenant que cette étape est faite il faut que je fasse la même chose en me servant des timers et j'aimerais votre avis pour aborder la façon de faire car là c'est plus la même chose. J'ai regardé ton programme de carillon Super_CinCi là c'est vraiment du lourd.
Bonne journée.
Marcus
Code: [Select]
// ARDUINO NANO IT Externe
#include <avr/io.h>
#include <stdint.h>                       // has to be added to use uint8_t
volatile uint8_t portbhistory = 0xFF;     // par défaut niveau HAUT parce que pull-up
volatile uint8_t changedbits;
#define F_CPU 16000000
#include <avr/interrupt.h>
/*
 * "avr / interrupt.h" le fichiers doit être inclus pour utiliser les interruptions.
 * Port B pins B8 à B13 sortie
 * Port D Pins D2 à D7 entrée
 * Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
*/
void setup()
{
Serial.begin(9600); 
cli(); //***********************  Deactive intteruption  *************************************
//************************************ init timer 0 ******************************************
/*
TCCR0A = 0x00;
TCCR0B = 0x00; 
TIMSK0 = 0x00;
TIMSK0  = (1 << TOIE0);// Permettre le débordement du Minuteur 0
TCCR0B |= (1 << CS10);// CS10 minuterie à la vitesse de l'horloge: 
//************************************* init timer2 ******************************************
TCCR2A = 0x00;
TCCR2B = 0x00;
TIMSK2 = 0x00;   
TIMSK2 = (1 << TOIE2);// Permettre le débordement du Minuteur 2
TCCR2B |= (1 << CS10);// CS10 minuterie à la vitesse de l'horloge:
// ************************************** Compaison des Tmers **********************************   
//OCR1A =  ;                      // compare le register
//TIMSK0 = bit (OCIE1A);          // interruption on Compare A Match
// *************************************** Configuration des ports *****************************
*/
//DDRB = 0x00; // Port B en Entrée broches de 8 à 13
 DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4) | (1 << DDB5));
// PB0,PB1,PB2,PB3,PB4,PB5 (PCINT0,PCINT1,PCINT2,PCINT3,PCINT4,PCINT5)
//PORTB = B11111111; // Etat Haut
PORTB |= ((1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2)| (1 << PORTB3)| (1 << PORTB4)| (1 << PORTB5));
DDRD =  0xfe; // Port D en Sortie broches de 0 à 7
PORTD = PORTD |0xfc; // Etat Haut
sei(); // *************************** Autorise les interruptions ******************************
PCICR |= (1 << PCIE0);    // PCIE0 pour permettre le scan PCMSK0
// ************************ déclencher une IT sur changement d'état ***************************
PCMSK0 = (1<<PCINT0)|(1<<PCINT1)|(1<<PCINT2)|(1<<PCINT3)|(1<<PCINT4)|(1<<PCINT5);
}
ISR (PCINT0_vect)
{
uint8_t SaveSREG = SREG; // save interrupt flag
changedbits = PINB ^ portbhistory;
portbhistory = PINB; 
// ***** CHANGEMENT D ETAT LOW/HIGH et HIGH/LOW sur une plusieurs pins ***** 
    if(changedbits & (1 << PINB0))
    { PORTD = ~(PORTD ^= ~(1 << (2)));}// PCINT1 change
    if(changedbits & (1 << PINB1))
    { PORTD = ~(PORTD ^= ~(1 << (3)));}// PCINT1 change
    if(changedbits & (1 << PINB2))
    { PORTD = ~(PORTD ^= ~(1 << (4)));}// PCINT2 change
    if(changedbits & (1 << PINB3))
    { PORTD = ~(PORTD ^= ~(1 << (5)));}// PCINT3 change
   if(changedbits & (1 << PINB4))
    {PORTD = ~(PORTD ^= ~(1 << (6)));}// PCINT4 change
    if(changedbits & (1 << PINB5))
    { PORTD = ~(PORTD  ^= ~(1 << (7)));}// PCINT5 change
SREG = SaveSREG;  // restore the interrupt flag
}

void loop()
{Serial.print ("PINB ");
Serial.print (PINB);
Serial.print ("PORT D ");
Serial.println (PORTD);
}

dfgh

#40
Sep 07, 2015, 02:39 pm Last Edit: Sep 07, 2015, 03:39 pm by dfgh
tu avance bien
au début de ma lecture de ton code, je ne pigeais pas pourquoi ces valeurs de 0xFe et 0xFC,
puis j'ai compris que tes commentaires n'étaient pas complets

j'aurais vu:
DDRD =  0xfe; // Port D en Sortie broches de 1 à 7 (sauf PD0 car RX)
PORTD = PORTD |0xfc; // Etat Haut  (sauf PD0 car RX et PD1 car TX)


 :)

au plaisir de te suivre

marcus_95

Merci je vais modifier.

jasonconvenant

Pourquoi regarder la lambda ?! Le calculateur se chargera d'enrichir ou non. Le simple fait d'augmenter le temps de 20% devrait suffire. Mais fait bien tes calculs car dans les hauts tours, tu risques d'injecter de l'essence alors que les soupapes se sont refermées.
J'ai déjà procédé comme ça avec un 4 cylindres, aucun problème.
Et par mesure de sécurité, tu ne devrais pas déconnecter les injecteurs du calculateur, c'est à toi de trouver une méthode non perturbatrice.
De plus, je n'ai pas pu voir ton schéma mais le fait que les injecteurs s'ouvrent rapidement est important. (mos + driver qui va bien) Un injecteur n'est rien d'autre qu'une bobine qui pompe du courant.
Bref bonne chance.

marcus_95

En effet si l'injection est trop longue il y a un risque d'injecté après la fermeture de la soupape, le carburant sera aspiré a la prochaine ouverture, le calculateur réduira l'injection car le lambda sera en dessous de 0.90  et mon boitier aussi.

marcus_95

mais pour l'instant mon plus gros problème est de trouvé comment utiliser "le timer 1 en PWM one shot, ainsi que l'interruption ICP1 pour lire aisément la durée légale d'injection" et "OCR1A = ICR1 + x" comme ma conseillé Super_Cinci et c'est une très bonne idée.

Go Up