centralina accensione motore

buongiorno
da poco più di due settimane ho acquistato la mia prima scheda arduino uno rev3
premetto che sono partito da 0 con la programmazione software, non avevo mai fatto niente di simile prima
in ogni caso essendo io un meccanico mi piacerebbe riuscire a creare per iniziare una centralina di accensione motore, e poi magari aggiungere gestione iniettori eccetera

per il momento ho attaccato una piccola calamita a una ventola per pc che leggo con un sensore di hall, e in corrispondenza della calamita c'è un piccolo adesivo bianco su una pala che viene illuminato dal led ad alta luminosità creando in questo modo una luce stroboscopica, io posso capire se il led viene acceso al momento giusto perchè vedo il piccolo adesivo, se anticipo o ritardo lo vedo spostarsi

con davvero tanti sforzi sono riuscito a creare questo codice (ho provato un sacco di soluzioni ma come ho detto per me è veramente materia sconosciuta)

con il codice sotto sfrutto il fatto che pulsein blocca il codice per il tempo della misurazione della calamita, poi me lo sblocca (e io interpreto la fine della calamita come puntozero per il mio ritardo), io faccio i mieie calcoli, attendo il tempo che devo attendere e accendo il led (so che la calamita è 50 gradi da misurazioni precedenti confrontanto la durata di pulsein low e di pulsein high)

ora io per attendere uso i delay perchè non riesco assolutamente a usare micros in modo che non funzionino, qualcuno può aiutarmi?
so che il codice fa pena probabilmente ma devo imparare :slight_smile:

int hall = 2 ;
int ledpin=13;

int durataon=100;
int gradidente=50;

unsigned long misuradente;

void setup( )
{
Serial.begin(9600);
pinMode(hall, INPUT);
pinMode(ledpin, OUTPUT);

}
void loop( )
{

misuradente = pulseIn(hall, LOW);

long tgiro= (misuradente/gradidente)*360;

long rpm=(1000000/tgiro)*60;
int gradiritardo=map(rpm, 600, 2000, 5, 20);
int ritardo=(tgiro/360)*gradiritardo;

delayMicroseconds(ritardo);
digitalWrite(ledpin, HIGH);
delayMicroseconds(durataon);

digitalWrite(ledpin, LOW);

Serial.print("rpm ");
Serial.print(rpm);
Serial.print(" / ");
Serial.print("ritardo ");
Serial.println(gradiritardo);

}

Il problema di una centralina per un motore di combustinone interna non é scrivere un codice funzionante ma conoscere tutta la teoria, funzionamento e parametri del motore in questione. Visto che la centralina regola anche il punto di lavoro in funzione del consumo minimo, della minimizzazione di produzione di ossidi di azoto e in funzione della concentrazione di ossigeno nei gas di scarico per fare funzionare il catalizzatore nei motori a benzina.

Ciao Uwe

dipende quale uso ne devi fare
un sistema elementare è più che sufficiente per gestire un vecchio motore a spinterogeno con regolatore di fase centrifugo...

Cerca nel forum. E' stata aperta una discussione simile per fare una centralina per un vecchio motore, diverse pagine di discussione. Magari puoi vedere se trovi qualcosa di interessante.

Comunque alla fine di tutto resta sempre il fatto che molta gente (me compreso) trova difficoltà ad usare decentemente i millis (non ricordo se i micros si usano allo stesso modo o come i delay), si sente l'effettiva necessità di una paginetta di spiegazione con 2-3 esempi semplici semplici; gli esempi allegati all'IDE non fanno che allontanarti ulteriormente dall'uso di questi comandi, ma proprio perché sfuggono i concetti elementari, come il fatto che ogni valore o variabile cambia in continuazione e quindi l'uso si basa su un continuo confronto di numeri aggiornati automaticamente. Io penso che basterebbe spiegare come si deve il blink, il debounce e come cicliegina l'uso all'interno di un interrupt, a quel punto ognuno potrebbe giocherellare con queste poche righe ben commentate e comprendere l'effettiva importanza di questi comandi. Oppure se qualcuno disponesse di un link sul quale la cosa è già spiegata bene me lo fornisca che lo aggiungo SUBITO nei link utili.

Mi hai dato l'incipit, tra qualche giorno metterò un articolo sul mio sito, così come ieri ho messo un articolo che spiega come manipolare le porte, altra cosa che in tanti chiedono :wink:

Concordo sull'inserimento di guide dettagliate :slight_smile:
Negli ultimi ultimi giorni ho letto davvero tonnellate di materiale riguardate interrupt, multitasking usando millis o micros ma difficilmente le dinamiche effettive di questi comandi sono ben spiegate
Per esempio pulsein blocca l'esecuzione del programma, solo per il tempo della lettura che gli viene ricjiesta o no? Non e chiaro....
Oppure come faccio a far partire un contatore che dopo un evento interrupt attende una variabile di tempo precedentemente calcolata prima di dare il via a jna nuova azione?

lucaleo:
Concordo sull'inserimento di guide dettagliate :slight_smile:
Negli ultimi ultimi giorni ho letto davvero tonnellate di materiale riguardate interrupt, multitasking usando millis o micros ma difficilmente le dinamiche effettive di questi comandi sono ben spiegate

Casomai il problema è la dispersione delle informazioni, nel senso che c'è tutto spiegato, solo che va cercato qua e là.

Per esempio pulsein blocca l'esecuzione del programma, solo per il tempo della lettura che gli viene ricjiesta o no? Non e chiaro....

Sul Reference è specificato è che pulseIn ferma il codice in attesa dell'impulso e lo misura. Se non arriva, si può specificare un timeout.
In entrambi i casi, la pulseIn ferma il codice.

Oppure come faccio a far partire un contatore che dopo un evento interrupt attende una variabile di tempo precedentemente calcolata prima di dare il via a jna nuova azione?

Ti devi scrivere il codice, se non lo trovi già pronto. L'Arduino non ha di suo questa funzione.
Non devi pensare che essendo l'Arduino un prodotto per principianti possa fare qualsiasi cosa senza conoscere un pò di elettronica e di informatica. :wink:

ovviamente non mi aspetto che sia tutto semplice :wink:
fortunatamente di elettronica un po' ne mastico, di programmazione no, ma come ho detto in queste due settimane ho letto davvero tonnellate di guide, modificato programmi gia esistenti eccetera, sono quindi piacevolmente stupito dai risultati che sono riuscito a ottenere senza basi

tuttavia quando intendo non siegato bene intendo dire che si trovano spiegazioni che lasciano spazio a interpretazioni...

la funzione pulsein per esempio
io ho letto il reference, e come giustamente hai scritto viene spiegato come opera
tuttavia nella pratica poi quella spiegazione a mio avviso non è così esauriente

io ho un sensore di hall, con il magnete davanti leggo low senza magnete high, con la riga di codice

durataoffhall = pulseIn(hall, LOW);

pulsein mi restituisce la durata in microsecondi di low (quindi calamita)
ora
io capisco che se non specifico il timeout e la mia calamita non inizia a girare ogni secondo pulse verrà superata e il codice andrà avanti
tuttavia se la calamita è in rotazione:
pulse blocca il codice solo per il periodo di low?
lo blocca per tutto il periodo high in attesa del nuovo impulso low?
come impulso per la funzione pulse si intende quello che abbiamo scritto nel comando (quindi nel mio esempio il low) o sempre high?

è questo quello che intendo dire io quando parlo della mancanza di spiegazioni dettagliate delle dinamiche, non lo dico perchè non mi soino informato, ma perchè (probabilmente avendo poche conoscenze essendo un principiante) leggendo davvero tonnellate di documentazione non riesco veramente a capire come operano queste funzioni....

leo72:
Mi hai dato l'incipit, tra qualche giorno metterò un articolo sul mio sito, così come ieri ho messo un articolo che spiega come manipolare le porte, altra cosa che in tanti chiedono :wink:

Ottimo Leo, le cose le sai spiegare benissimo, è tutta roba che vale oro per noi neofiti XD

i millis...dannati :smiley: in ogni caso sapete reindirizzarmi in una pagina dove c'è un post fatto bene sui ritardi senza la funzione delay() ?

Vedi qui:

ritorno tanto tempo con delle belle notizie

sono riuscito a buttare giu un programmino che funziona piuttosto bene grazie alla libreria stop watch che rende uso di micros() e quanto altro semplicissimo

il delay per l'accensione del led serve perchè ho 2 stroboscopiche che illuminano un dente su una ventola adesso per controllare come lavora

in realtà in futuro i pin delle bobine saranno sempre su high per caricare le bobine e andranno su low solo al momento della scintilla, voglio anche aggiungere una sicurezza che imposta a low i pin delle bobine se per 1 secondo non arrivano istruzioni per evitare danni vari

suggerite pure modifiche!!

//libreria stopwatch
#include <StopWatch.h>

//cilindri 1 e 4
int led1 = 13;

//cilindri 2 e 3
int led2=12;

//interrupt startt
int pin2=2;

// interrupt stopp
int pin3=3;

//stato normale startt
volatile int statestartt = HIGH;

//stato normale stopp
volatile int statestopp=HIGH;

//timer durata dente
StopWatch sw_micros(StopWatch::MICROS);

//timer attesa 1 e 4
StopWatch sw_micros1(StopWatch::MICROS);

//timer attesa 2 e 3
StopWatch sw_micros2(StopWatch::MICROS);


//valore durata dente microsecondi
int time=0;

//gradi ritardo da fine dente
int ritardo=90;

//valore durata ritardo in microsecondi 1 e 4
int tritardo1=0;

//valore durata ritardo in microsecondi 2 e 3
int tritardo2=0;

//numero giri
int rpm=0;

//ampiezza dente in gradi
int gradidente=40;








void setup()
{
  //comunicazione seriale
  Serial.begin(9600);
  
  //bobina 1 e 4
  pinMode(led1, OUTPUT);
  
  //bobina2 e 3
  pinMode(led2, OUTPUT);
  
  //interrupt in inizio dente
  attachInterrupt(0, startt, FALLING);
  
  //interrupt fine dente
  attachInterrupt(1, stopp, RISING);
  
  //pullup interrupt startt
digitalWrite(pin2, HIGH);

//pullup interrupt stopp
digitalWrite(pin3, HIGH);
}

void loop()
{
  
  if(statestartt==LOW){//se il dente è iniziato
    sw_micros.start();//inizia a contare durata dente
      statestartt=HIGH;// reimposta startt
        }
        
     if(statestopp==LOW){//se il dente è finito
       time=sw_micros.elapsed();//memorizza durata dente
    sw_micros1.start();//inizia a contare da fine dente per 1 e 4
     sw_micros2.start();//inizia a contare da fine dente per 2 e 3
    Serial.println(time);//stampa durata dente
    statestopp=HIGH;//reimposta stopp
    sw_micros.reset();//azzera timer durata dente
     tritardo1=(time/gradidente)*ritardo;//calcola durata ritardo in microsecondi per 1 e 4
      tritardo2=(time/gradidente)*(ritardo+180);//calcola durata ritardo in microsecondi per 2 e 3
  
    rpm=60000000/((time/gradidente)*360);//calcolo rpm
    Serial.println(rpm);//stampo rpm
     }
     
     
        
        
        
   if(sw_micros1.elapsed()>tritardo1){//se il tempo che è passato dalla fine del dente è maggiore della durata del ritardo
     sw_micros1.reset();//azzera timer ritardo
      digitalWrite(led1, HIGH);//accendi led
       delayMicroseconds(500);
      digitalWrite(led1, LOW);//spegni led
  
      
      } 
      
     if(sw_micros2.elapsed()>tritardo2){//se il tempo che è passato dalla fine del dente è maggiore della durata del ritardo
     sw_micros2.reset();//azzera timer ritardo
      digitalWrite(led2, HIGH);//accendi led
     delayMicroseconds(500);
      digitalWrite(led2, LOW);//spegni led
 
      
      }  
    

}

void startt()//interrupt startt
{
  statestartt = !statestartt;//inverti startt
}


void stopp()//interrupt stopp
{
  statestopp = !statestopp;//inverti stopp
}

sí, ho un suggerimento: usa i CODE-Tag al post delle QUOTE-Tag per lo sketch.
Ciao Uwe

Va bene ho usato la funzione copia per il forum dell'ide credevo andasse bene....
Quello che.vorrei sapere e se.ci sono alcune modifiche evidenti da fare agli occhi di un programmatore che sa realmente quello che fa...
Appena finisco di realizzare l'hardware e dopo aver inserito l'anticipo variabile con map () lo piazzo su un motore...

Si.
Puoi sostitutire

  //pullup interrupt startt
digitalWrite(pin2, HIGH);

//pullup interrupt stopp
digitalWrite(pin3, HIGH);

con

pinMode(pin2, INPUT_PULLUP);
pinMode(pin3, INPUT_PULLUP);

prima degli attachinterrupt, è più corretto.

grazie!!
modifica fatta

//libreria stopwatch
#include <StopWatch.h>

//cilindri 1 e 4
int led1 = 13;

//cilindri 2 e 3
int led2=12;

//interrupt startt
int pin2=2;

// interrupt stopp
int pin3=3;

//stato normale startt
volatile int statestartt = HIGH;

//stato normale stopp
volatile int statestopp=HIGH;

//timer durata dente
StopWatch sw_micros(StopWatch::MICROS);

//timer attesa 1 e 4
StopWatch sw_micros1(StopWatch::MICROS);

//timer attesa 2 e 3
StopWatch sw_micros2(StopWatch::MICROS);


//valore durata dente microsecondi
int time=0;

//gradi ritardo da fine dente
int ritardo=90;

//valore durata ritardo in microsecondi 1 e 4
int tritardo1=0;

//valore durata ritardo in microsecondi 2 e 3
int tritardo2=0;

//numero giri
int rpm=0;

//ampiezza dente in gradi
int gradidente=40;








void setup()
{
  //comunicazione seriale
  Serial.begin(9600);
  
  //bobina 1 e 4
  pinMode(led1, OUTPUT);
  
  //bobina2 e 3
  pinMode(led2, OUTPUT);
  
  pinMode(pin2, INPUT_PULLUP);
  
  pinMode(pin3, INPUT_PULLUP);
  
  //interrupt in inizio dente
  attachInterrupt(0, startt, FALLING);
  
  //interrupt fine dente
  attachInterrupt(1, stopp, RISING);
  

}

void loop()
{
  
  if(statestartt==LOW){//se il dente è iniziato
    sw_micros.start();//inizia a contare durata dente
      statestartt=HIGH;// reimposta startt
        }
        
     if(statestopp==LOW){//se il dente è finito
       time=sw_micros.elapsed();//memorizza durata dente
    sw_micros1.start();//inizia a contare da fine dente per 1 e 4
     sw_micros2.start();//inizia a contare da fine dente per 2 e 3
    Serial.println(time);//stampa durata dente
    statestopp=HIGH;//reimposta stopp
    sw_micros.reset();//azzera timer durata dente
     tritardo1=(time/gradidente)*ritardo;//calcola durata ritardo in microsecondi per 1 e 4
      tritardo2=(time/gradidente)*(ritardo+180);//calcola durata ritardo in microsecondi per 2 e 3
  
    rpm=60000000/((time/gradidente)*360);//calcolo rpm
    Serial.println(rpm);//stampo rpm
     }
     
     
        
        
        
   if(sw_micros1.elapsed()>tritardo1){//se il tempo che è passato dalla fine del dente è maggiore della durata del ritardo
     sw_micros1.reset();//azzera timer ritardo
      digitalWrite(led1, HIGH);//accendi led
       delayMicroseconds(500);
      digitalWrite(led1, LOW);//spegni led
  
      
      } 
      
     if(sw_micros2.elapsed()>tritardo2){//se il tempo che è passato dalla fine del dente è maggiore della durata del ritardo
     sw_micros2.reset();//azzera timer ritardo
      digitalWrite(led2, HIGH);//accendi led
     delayMicroseconds(500);
      digitalWrite(led2, LOW);//spegni led
 
      
      }  
    

}

void startt()//interrupt startt
{
  statestartt = !statestartt;//inverti startt
}


void stopp()//interrupt stopp
{
  statestopp = !statestopp;//inverti stopp
}

a giudicare dalle poche "sgridate" sembra che abbia fatto un buon lavoro
meno male perchè quindi continuo su questa strada
in effetti sono contento perchè penso di aver trovato un modo molto semplice di fare quello che mi serve al posto delle cose complicatissime che si trovano in rete e che sembra comunque molto preciso...

chiunque abbia suggerimenti anche nel caso stravolgano tutto il codice è il benvenuto!!

Più compatto lo capisco meglio

#include <StopWatch.h>

const byte led1 = 13;    // cilindri 1 e 4
const byte led2 = 12;    // cilindri 2 e 3
const byte pin2 = 2;     // interrupt startt
const byte pin3 = 3;     // interrupt stopp

volatile int statestartt = HIGH;    // stato normale startt
volatile int statestopp=HIGH;       // stato normale stopp

StopWatch sw_micros(StopWatch::MICROS);    // timer durata dente
StopWatch sw_micros1(StopWatch::MICROS);   // timer attesa 1 e 4
StopWatch sw_micros2(StopWatch::MICROS);   // timer attesa 2 e 3

int time = 0;           //valore durata dente microsecondi
int ritardo = 90;       //gradi ritardo da fine dente
int tritardo1 = 0;      //valore durata ritardo in microsecondi 1 e 4
int tritardo2 = 0;      //valore durata ritardo in microsecondi 2 e 3
int rpm = 0;             //numero giri
int gradidente = 40;     //ampiezza dente in gradi

void setup() {
  Serial.begin(9600);     //comunicazione seriale
  pinMode(led1, OUTPUT);  //bobina 1 e 4
  pinMode(led2, OUTPUT);  //bobina2 e 3
  pinMode(pin2, INPUT_PULLUP);
  pinMode(pin3, INPUT_PULLUP);
  attachInterrupt(0, startt, FALLING);   //interrupt in inizio dente
  attachInterrupt(1, stopp, RISING);     //interrupt fine dente
}

void loop()
{
  //se il dente è iniziato
  if(statestartt == LOW){
    sw_micros.start();//inizia a contare durata dente
    statestartt=HIGH;// reimposta startt
  }

  //se il dente è finito
  if(statestopp == LOW) {
    time=sw_micros.elapsed();                  //memorizza durata dente
    sw_micros1.start();                        //inizia a contare da fine dente per 1 e 4
    sw_micros2.start();                        //inizia a contare da fine dente per 2 e 3
    Serial.println(time);                      //stampa durata dente
    statestopp = HIGH;                         //reimposta stopp
    sw_micros.reset();                         //azzera timer durata dente
    tritardo1=(time/gradidente)*ritardo;       //calcola durata ritardo in microsecondi per 1 e 4
    tritardo2=(time/gradidente)*(ritardo+180); //calcola durata ritardo in microsecondi per 2 e 3
    rpm=60000000/((time/gradidente)*360);      //calcolo rpm
    Serial.println(rpm);                       //stampo rpm
  }

  //se il tempo che è passato dalla fine del dente è maggiore della durata del ritardo
  if(sw_micros1.elapsed() > tritardo1){
    sw_micros1.reset();                        //azzera timer ritardo
    digitalWrite(led1, HIGH);                  //accendi led
    delayMicroseconds(500);
    digitalWrite(led1, LOW);                    //spegni led
  } 

  //se il tempo che è passato dalla fine del dente è maggiore della durata del ritardo
  if(sw_micros2.elapsed()>tritardo2){
    sw_micros2.reset();                          //azzera timer ritardo
    digitalWrite(led2, HIGH);                    //accendi led
    delayMicroseconds(500);
    digitalWrite(led2, LOW);                      //spegni led
  }  
} // End Loop

void startt()//interrupt startt
{
  statestartt = !statestartt;  //inverti startt
}

void stopp()//interrupt stopp
{
  statestopp = !statestopp;    //inverti stopp
}

così fa una gran figura ahaha

il codice è migliorato sensibilmente trasformanto time, tritardo1 e tritardo2 in long
sotto un certo numero di giri non riusciva più a tenere i micros direi e led2 si spegneva...