Résolu Boitier E85 avec un Arduino nano

Programme dans "Réalisations et Projets Finis"

Bonjour, je suis nouveau sur le forum et débutant en programmation. Merci de votre compréhension.
Donc je travaille sur un projet d'un boitier pour rouler avec du E85 avec un ARDUINO NANO pour un moteur V6. J'ai fait un code qui fonctionne presque bien, au ralenti pas de problème à partir de 3000 Tr/mn il ne fonctionne plus car mon code ne fait pas les commutations de broches en même temps. J'ai recherché un moyen par les interruptions mais je n'y comprends rien (je débute).
Le principe du code est de lire la sonde lambda et de rajouté du temps d'injection par pas de 1%, donc calcul du temps d'injection en maintenant la broche a l'état bas et rajouter 1% sauf qu'a 3000Tr/mm il y faut commuter une autre broche en plein milieu de la première. J'ai vue ça avec un analyseur logique.
Avez-vous une idée pour faire cela?

Un grand merci a dfgh.

E85-V6-Vref.h (64 KB)

donne nous ton code, ce sera plus facile :slight_smile:

Tu m'intéresse beaucoup la, moteur V6 de quelle marque?

Bonjour, voici le code


Plutôt léger comme code xD

*************************************************************************************************************************
****************************************************************************************************************************
****************************************************************************************************************************
******************************************          BROCHAGES ARDUINO NANO                  ********************************
****************************************************************************************************************************
********        Entrée injecteur 1 sur la broche 8  Sortie injecteur 1 sur la broche 2      ********************************
********        Entrée injecteur 2 sur la broche 9  Sortie injecteur 2 sur la broche 3      ********************************
********        Entrée injecteur 3 sur la broche 10 Sortie injecteur 3 sur la broche 4      ********************************
********        Entrée injecteur 4 sur la broche 11 Sortie injecteur 4 sur la broche 5      ********************************
********        Entrée injecteur 5 sur la broche 12 Sortie injecteur 5 sur la broche 6      ********************************
********        Entrée injecteur 6 sur la broche 13 Sortie injecteur 6 sur la broche 7      ********************************
********        Capteur température d'eau moteur broche A2 1-whire                         ********************************
********        Sonde LAMBDA A3  analogique avec conversion en volt                          ********************************
********        Sauvegarde de la valeur broche A4 LOW                                       ********************************
********        Blocage du programme mode normal broche A5 LOW                             ********************************
********        Passage de la valeur a 25% d'un coup broche A6  LOW                         ********************************
****************************************************************************************************************************
*/
#include <EEPROM.h>
#include <OneWire.h>
long int cmpt;         // compteur d'injection
int valeur=0;          // Pourcentage E85 mis en mémoire dans l'EEPROM
int valeur2;           // Pour le stater
float temp = 0 ;       // Température eau
long int cmpt3;        // Résultat opération d'injection
float Lmda;            // Sonde Lambda
long int valeur3;      // Pour le passage du LAMDBA
int x;                 // PORTB
int z;                 //PORTD
// moyenePin  = A1;   // Valeur a 25%
int analogPin = A2;    //initialisation de la sonde Lambda sur A2 (analogique)
                      // entre 0.9 et 1 volt a mesurer
//              A3   // Broche utilisée pour le bus 1-Wire 
//  savePin =   A4;  // Sauvegarde de la valeur dans l'EEPROM
//  resetPin =  A5;  // Reset valeur

int t_lambda_S;      // pour le blocage du LAMBA  et du starter  
unsigned long time2; // Pour le calcul du temps Lambda/Starter
unsigned long time;  // Temps de fonctionnement du programme
unsigned long time3; // Temps pour l'injection
// VARIABLES POUR LES INJECTEURS Entrés Sorties
byte S_inj_[7]={2,3,4,5,6,7,8};
byte E_inj_1;
byte E_inj_2;
byte E_inj_3;
byte E_inj_4;
byte E_inj_5;
byte E_inj_6;
byte inj_[7]={0,1,2,3,4,5,6};
//****************************************************** récupérer sur le net pour le calcul de la température moteur
#define DS18B20 0x28     // Adresse 1-Wire du DS18B20
#define BROCHE_ONEWIRE A3 // Broche utilisée pour le bus 1-Wire
OneWire ds(BROCHE_ONEWIRE); // Création de l'objet OneWire ds
// Fonction récupérant la température depuis le DS18B20
// Retourne true si tout va bien, ou false en cas d'erreur
boolean getTemperature(float *temp){ // data : Données lues depuis le scratchpad
  byte data[9], addr[8]; // addr : adresse du module 1-Wire détecté
   if (!ds.search(addr)) { // Recherche un module 1-Wire
    ds.reset_search();    // Réinitialise la recherche de module
    return false;   }     // Retourne une erreur
   if (OneWire::crc8(addr, 7) != addr[7]) // Vérifie que l'adresse a été correctement reçue
    return false;         // Si le message est corrompu on retourne une erreur
  if (addr[0] != DS18B20) // Vérifie qu'il s'agit bien d'un DS18B20
    return false;         // Si ce n'est pas le cas on retourne une erreur
  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  ds.write(0x44, 1);      // On lance une prise de mesure de température
  delayMicroseconds(20);   // Et on attend la fin de la mesure 4 micros seconde.
  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  ds.write(0xBE);         // On envoie une demande de lecture du scratchpad
  for (byte i = 0; i < 9; i++) // On lit le scratchpad
    data[i] = ds.read();  // Et on stock les octets reçus
    *temp = ((data[1] << 8) | data[0]) * 0.0625; // Calcul de la température en degré Celsius
  return true;            // Pas d'erreur  
}
//_____________________________________________________________________________________________________________________
//_________________________________________________________  DEBUT DU SETUP  __________________________________________
//_____________________________________________________________________________________________________________________
void setup()
{
//**********************************************************************************************************************
//                                      Lecture de la valeur à l'adresse 500 de l'EEPROM
valeur = EEPROM.read(500);
valeur2=(valeur);

//**********************************************************************************************************************
//              on met les broches pour les injecteurs en entrée et a l'état HAUT (port B de 8 à 13)
//              on met les broches 0 à 7 en sortie (port D de 0 à 7) (0 et 1 sont les broches Rx Tx) et a l'etat Haut
DDRB = B00000000;   
PORTB = B11111111;  
DDRD =  B11111111; 
PORTD = PORTD |B11111100;  
//***********************************************************************************************************************
(getTemperature(&temp));//                 Lecture de la température une fois, ralentis le programme.               *****
//***********************************************************************************************************************
time = millis(); // Initialisation du temps
time3 = micros(); // Initialisation pour le temps d'injection
//-----------------------------------------------------------------------------------------------------------------------
for (int z=0; z<=7; z++) // compteur pour les varibles
{byte E_inj_[z];byte inj_[x];}
//************************************************************************************************************************
//                            Starter a 50% si température < 30° et si  15%  en plus en memmoire                     *****
//************************************************************************************************************************
if ((temp < 30.00) && (valeur >= 115))// environ 15%
{t_lambda_S=1; valeur=153;}// starter a 50%
else
{t_lambda_S=2; valeur=0;}// mode normal
}
//************************************************************************************************************************
//                                                       CALCUL DU LAMBDA  (INT LAMBDA)                              *****
//************************************************************************************************************************
int lambda (int valeur3)
{ 
// on lit le LAMBDA                           
         Lmda = (analogRead(A2)*5.0) / 1024 ;            
// On regle le LAMBDA entre 0.95 et 1.05 par pas de 0.1%  
// moins 0.1%             
       if (Lmda < 0.95)
        {valeur = (valeur -0.5); if (valeur<1){valeur=0;}} // blocage à 0% = 1µs
// plus 0.1%       
       if (Lmda > 1.05)
        {valeur = (valeur +0.5);if (valeur>140){valeur=140;}}
        
// blocage a 40% 
}
/***********************************************  FONCTIONNEMENT   ********************************************************     
***    Temps d'injection entre 3 et 5ms a 650 T/mn 11 tours/s à 6000 T/mn 100T/s 300 injections/T                       ***
***    ordre d'allumage V6 1.4.3.6.2.4. 3 explosions par tour.                                                          ***
***    Le calculateur voiture talonner si il y a du E85, le programme vas ajouter du temps car le Lambda > a 1.          ***
***    Si pas de E85 le calculateur voiture vas réguler l'injection.                                                    ***
***    On va mesurer le Lambda toute les 10 secondes pour laisser du temps au calculateur.                              ***
***    Si la température d'eau > 30° (variable temps) pas de starter.                                                   ***
***    Si température < 30° on passe en mode starter a 50% pendant 10 secondes si la valeur de l'EEPROM > 15%         ***
***    Problème qui peut se produire: le calculateur diminue le temps d'injection et le programme ajoute du temps,      ***
***    jusqu’au moment où le calculateur sera en talon bas pour cette raison on ne dépasse pas les 40% d'injection maxi ***
***                                                                                                                     ***
***           ++++++++++++++++++++++++++++++++  GESTION DES INJECTEURS  ++++++++++++++++++++++++++++                    *** 
***                                                                                                                     ***
***    Le calculateur commande les injecteurs par un état BAS. On scrute les injecteurs sur le port B.                  ***
***    On bloque la broche du port D à l'état BAS et on compte.                                                         ***
***    On règle l’injection pour avoir un l'LAMBDA entre 0.95 (trop d'essence) et 1.05 (trop d'air) par pas de 0.5%.    ***
***************************************************************************************************************************
*/
//**************************************************  PROGRAMME INJECTION  (INT INJECTEUR) ********************************
int injecteur(float valeur,int z, int x)//passage de variable pour enrichissement du mélange
// "valeur" pour l'injection en plus    "Z" pour le PORTD    "X" pour le PORTB 
// Temps pris par le programme pour le changement d'état entre 8 et 10µs.
{
while ((PINB & (1 << x))>>x== LOW)
{; PORTD = ~(1 << (z)); }  // On passe la sortie a 0 et on attend le changement d'état
cmpt= (micros() - time3);time3=micros();cmpt3=cmpt*(valeur/1000);// calcule pour le temps d'injection suivant le LAMBDA
delayMicroseconds(cmpt3);// injection en plus
 PORTD = ~(0 << (z));
 cmpt=0;cmpt3=0;// on remet la sortie a 1 
}
//________________________________________________________________________________________________________________________
//________________________________________________         FIN DU SETUP      _____________________________________________
//________________________________________________________________________________________________________________________
//...
//................................................                                 .......................................
//................................................   BOUCLE PROGRAMME PRINCIPAL    .......................................
//................................................                                 .......................................
//...
void loop(){                                                                                       
//********************************************* MISE EN PLACE DES VARIABLES INJECTEURS ***********************************
E_inj_1 = (PINB & (1 << 0));                                                         
E_inj_2 = (PINB & (1 << 1))>>1;                                                      
E_inj_3 = (PINB & (1 << 2))>>2;                                                      
E_inj_4 = (PINB & (1 << 3))>>3;                                                      
E_inj_5 = (PINB & (1 << 4))>>4;                                                      
E_inj_6 = (PINB & (1 << 5))>>5;                                                     
//****************************************** Suivant l'injecteur on passe les paramètres *********************************
if (E_inj_1 == LOW)
{z=2;x=0;inj_[x]= E_inj_1; injecteur (valeur,z,x);}
if (E_inj_2 == LOW)
{z=3;x=1;inj_[x]= E_inj_2; injecteur (valeur,z,x);}
if (E_inj_3 == LOW)
{z=4;x=2;inj_[x]= E_inj_3; injecteur (valeur,z,x);}
if (E_inj_4 == LOW)
{z=5;x=3;inj_[x]= E_inj_4; injecteur (valeur,z,x);}
if (E_inj_5 == LOW)
{z=6;x=4;inj_[x]= E_inj_5; injecteur (valeur,z,x);}
if (E_inj_6 == LOW)
{z=7;x=5;inj_[x]= E_inj_6; injecteur (valeur,z,x);}
//****************************************************** LAMBDA  *********************************************************
  if  ((t_lambda_S==1) && (millis() - time2 > 10000)) // 10 seconde passage en normale si starter
      {time2= millis(); valeur=valeur2; t_lambda_S=2;}// pour la lecture du LAMBDA dans 10 minutes
  
  if  (( t_lambda_S == 2) && (millis() - time2 > 60000))// lectures du LAMBDA après 10 minutes
      {time2= millis();t_lambda_S=3;lambda(valeur3=10);}// blocage 
 
  if  ((t_lambda_S ==3) && (millis() - time2 > 10000))// lecture du LAMBDA toutes les 10 secondes après les 10 minutes
       {time2= millis();lambda(valeur3=10);}     
//***************************************************************** EEPROM ************************************************  
// Mise en mémoire du pourcentage de E85 à l'adresse 500 si la broche "X" est a l'état bas, coupure du contact et maintien
// par condo pour sauver la valeur
if ((PINC & (1 << 4))>>4 == LOW) 
{EEPROM.write(500, (valeur));delay(50); PORTC |=_BV(PC4);}
//**************************************************** RESET VALEUR *******************************************************
if ((PINC & (1 << 5))>>5 == LOW) 
{EEPROM.write(500, (valeur=0));delay(50); PORTC |=_BV(PC5); valeur=0;}
//**************************************************** PASSAGE A 25% D'UN COUP *******************************************
if ((PINC & (1 << 1))>>1 == LOW) 
{EEPROM.write(500, (valeur=125));delay(50); PORTC |=_BV(PC1); valeur=125;}
}

Désoler je n'arrive pas a le faire en une fois.
Pour la voiture c'est une C5 v6.
Cordialement.
Marcus.

Le schéma et le CI en simple face.

hello
pour un néophyte en mécanique, le système, c'est quoi ?

ce que je crois savoir:
normalement, le calculateur " calcule un temps d'injection, il met à low les injecteurs chacun à leur tour en fonction de l'ordre d'allumage pour le type de moteur.

mes questions:

le principe, c'est quoi? la sonde lambda te donne une température, et en fonction de cette température, tu modifies le ratio du mélange air/essence pour arriver à une explosion optimale qui aura la température idéale ?

ton système regarde en boucle l'état des commandes d'injecteur et lorsqu'un injecteur est à low, si la sonde lambda le demande, il fait un calcul d'allongement ou pas du temps à LOW.

ton calculateur est toujours en service. comment peux tu raccourcir le temps alors que le calculateur demande un temps plus long que ton système? le calculateur fais son boulot et va maintenir le temps initial.

si tu maintiens le temps des injecteurs plus longtemps, et que tu repiques la cde des injecteurs en entrée de ton système, ne craint tu pas que la sortie boucle sur l'entrée ?

bon après reflexion, je pense que les sorties du calculateur entrent dans ton montage et que seules les sorties de ton montage sont raccordées aux injecteurs.
là, tout devient possible. :slight_smile:

maintenant, c'est quoi cette 2ème sortie qui doit être actionnée au milieu du temps de la 1ère.
que fait elle? il y a 1 sortie supplémentaire pour chaque injecteur?

lorsque tu fais

cmpt= (micros() - time3);time3=micros();cmpt3=cmpt*(valeur/1000);// calcule pour le temps d'injection suivant le LAMBDA
delayMicroseconds(cmpt3);// injection en plus

tu pourrais faire:

cmpt= (micros() - time3);time3=micros();cmpt3=cmpt*(valeur/1000);
si nb_tours>3000
{
delayMicroseconds(cmpt3/2);// 1/2 temps injection en plus
2ème sortie=1;
delayMicroseconds(cmpt3/2);// 1/2 temps injection en plus
}
else
{
delayMicroseconds(cmpt3);// 1/1 temps injection en plus
}

Je ne peux pas prendre en considération le régime moteur, risque de ralentissement du programme et pas utile pour les commutations, en fait ce que je recherche c'est de commuter une sorties compter le temps et si une autre commande intervient faire la même chose toute en regardant si il y a un changement d'état pour allonger ou diminuer le temps. Car mon programme le fait broche par broche. Ce soir je mets la photo des commutations prise par l'Analyzer logique pour mieux comprendre.
La sonde lambda est un capteur pour l'anti-pollution et avoir une combustion parfaite du mélange. Elle doit être à 1 (1V) pour être parfait.

Le calculateur se fit à la sonde lambda pour réguler le temps d'injection, avec du E85 il faut augmenter ce temps entre 20 et 25%, le calculateur fait le reste.
Le programme ne peut pas diminuer le temps d'injection c'est au calculateur de le faire, c'est pour cela que j'ai volontairement bridé a 1 le minimum et 40% au maxi.

tu es en train de dire :
que ton prg lis la sonde toutes les 10 secondes et fais ses corrections en fonction de sa lecture.

que tu veux lire la sonde en permanence pour modifier la correction de temps d'ouverture en temps réel

c'est bien ça?

lecture du lambda après 10mn et toutes les 10s.
10mn pour le chauffage du moteur.
10s pour le réglage du lambda en temps réel.

En fait je recherche un code qui utiliserais:
PCINT3 Interruption externe sur les broches 0 à 7
LOW : l’interruption est déclenchée quand la broche concernée est LOW.

attachInterrupt(numéro, ISR, mode);

a savoir si c'est possible pour mon montage.

Si c'est pour gérer les interruptions sur un port tu peux lire mon tuto : Interruptions ATMega 328p - Tutoriels et cours - Arduino Forum

Pas de fonctions arduino attachInterrupXXXXt().
C'est de la gestion directement par les registres, cela reste très simple car en programation je ne sais pas faire des choses compliquées.

Merci je vais le lire a tête reposée.

Voilà je mets les images pour mieux comprendre mon problème.

ok, là on comprend tout de suite le problème

par contre, tu veux compter sur deux timers, mais qu'en est il de la pompe?
n'est elle pas perturbée de devoir fournir sur deux injecteurs en même temps?

en supposant que non, le temps de recouvrement sur 2 injecteurs doit fausser le débit et devrait, je suppose, demander un allongement supplémentaire du temps d'injection ?

Non là c'est en mode réel constructeur sortie du calulo. Oui en effet je veux compter sur 2 timers en me servant si possible des interruptions pour gagner du temps dans le programme