# Accensione elettronica motore termico

**URL:** <https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325>\
**Category:** Generale\
**Created:** [May 10, 2022, 1:14pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325 "2022-05-10T13:14:40Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 10, 2022, 1:14pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/1 "2022-05-10T13:14:40Z")

</div>

Ciao a tutti! Mi chiamo Marco. Sono nuovo del forum e nel mondo di Arduino. Sono appassionato di motori e elettronica. Sto realizzando (ci sto provando più che altro) una accensione ad anticipo variabile per un motore due tempi. Ho già letto altri post esistenti da cui ho preso spunto per realizzare il mio codice, quindi dovrebbe essere tutta roba già vista.  
Un sensore hall dovrà rilevare la posizione del volano (tramite un magnete incollato ad esso) e inviare il segnale ad Arduino, il quale calcolerà l'anticipo (al variare dei giri motore) e, tramite un mosfet, piloterà la bobina alta tensione.  
Per ora sto semplicemente accendendo un led quando il magnete passa sul sensore. Allego il codice:

```cpp
#include <StopWatch.h>

const byte led = 12; // bobina
const byte pin = 2; // sensore hall

volatile int hallstate = HIGH; // stato magnete

StopWatch sw_micros(StopWatch::MICROS); // contatore periodo

long time = 0; //periodo 
long rpm = 0; //numero giri

void setup() {
  Serial.begin(9600);                     
  pinMode(led, OUTPUT); //bobina 
  pinMode(pin, INPUT_PULLUP); //pullup sensore
  attachInterrupt(0, magnete, RISING); //interrupt passaggio magnete
  sw_micros.start(); //inizia a contare periodo
}

void loop(){
  if(hallstate == LOW){
    time=sw_micros.elapsed(); //memorizza periodo
    sw_micros.reset(); //azzera timer periodo
    sw_micros.start(); //riavvia il contatore
    hallstate = HIGH; //reimposta hallstate
    
    scintilla(); //void scintilla
    Serial.println(time); //stampa durata periodo
    Serial.print("\t");
    rpm=60000000/time; //calcolo rpm
    Serial.println(rpm); //stampo rpm
   }
  
} 

void scintilla()
{
  digitalWrite(led, HIGH); //accendi bobina
  delayMicroseconds(1000);
  digitalWrite(led, LOW); //spegni bobina
}

void magnete() 
{
  hallstate = !hallstate ; //passaggio magnete
}

```

Il problema è che nel monitor seriale io vedo valori assurdi. Ad un singolo passaggio del magnete compaiono almeno tre letture diverse, delle quali solo una è più o meno precisa. Ho pensato che il problema possa essere il sensore hall (che dovrebbe essere un KY-024) che all'avvicinarsi/allontanarsi del magnete fa delle false letture. Esiste un modo per "pulire" il segnale digitale? Sempre che non sia un errore nel codice.  
Grazie mille a tutti.

---

<div class="post-metadata">

**Author:** ![Z4KK4](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/z4kk4/32/1126465_2.png) [@Z4KK4](https://forum.arduino.cc/u/Z4KK4)\
**Post date:** [May 10, 2022, 1:33pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/2 "2022-05-10T13:33:08Z")

</div>

Ciao, non sono sicurissimo che il problema si questo ma nella definizione dell'interrupt hai messo 0 e non 2 (pin al quale hai collegato il sensore hall)

---

<div class="post-metadata">

**Author:** ![gpb01](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gpb01/32/830685_2.png) [@gpb01](https://forum.arduino.cc/u/gpb01)\
**Post date:** [May 10, 2022, 1:40pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/3 "2022-05-10T13:40:26Z")

</div>

Dipende da che board usa ... in realtà, con quel parametro, andrebbe proprio passato il numero di interrupt utilizzato e quindi, nel caso di Arduino UNO, il pin 2 è proprio equivalente all'interrupt 0.

Dato che però non sempre la cosa è così semplice, la cosa migliore è affidarsi ad un'apposita funzione che ritorna il numero di interrupt in funzione del piedino ed usare nella attachInterrupt() ovvero fare:

`attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);`

Quindi, se sta usando una UNO, va bene (_anche se è il metodo meno raccomandabile_), in caso contrario non è detto ...

Guglielmo

---

<div class="post-metadata">

**Author:** ![Standardoil](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/standardoil/32/1235732_2.png) [@Standardoil](https://forum.arduino.cc/u/Standardoil)\
**Post date:** [May 10, 2022, 2:31pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/4 "2022-05-10T14:31:56Z")

</div>

> [@mark205](#):
>
> compaiono almeno tre letture diverse, delle quali solo una è più o meno precisa.

fai un esempio, per cortesia?  
indicando anche le condizioni di contorno (numero di giri)

comunque propendo anch'io per false letture, magari provare a mettere un gruppo RC all'ingresso...

---

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 10, 2022, 3:03pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/5 "2022-05-10T15:03:07Z")

</div>

Grazie per le risposte. La scheda è una uno. Anche modificando il codice come dice Guglielmo il problema persiste.  
A circa 900 giri mi appaiono questi valori: (a sinistra il periodo e a destra gli rpm)

```cpp
66380 903
8536 7029
64692 927
10044 5973
1556 38560
65736 912
7044 8517
66600 900
2388 20080  

```

Inoltre il periodo mi esce in millisecondi, ma nel codice io sto contando in microsecondi. Forse sbaglio a dichiarare la variabile come long?

Per quanto riguarda il gruppo rc, in teoria non vado a ritardare di alcuni microsecondi la lettura? Dovendo gestire differenze di anticipo anche nell'ordine dei 2/3 gradi ho bisogno della massima precisione.  
Il sensore che sto utilizzando ha un trimmer, ho provato a regolarlo ma la situazione non cambia.  
Grazie

---

<div class="post-metadata">

**Author:** ![gpb01](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gpb01/32/830685_2.png) [@gpb01](https://forum.arduino.cc/u/gpb01)\
**Post date:** [May 10, 2022, 3:12pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/6 "2022-05-10T15:12:15Z")

</div>

> [@mark205](#):
>
> Anche modificando il codice come dice Guglielmo il problema persiste.

Ovvio, sei su una UNO, non cambia nulla ... è con le SAMD che è meglio usare quella forma per evitare di sbagliare.

Guglielmo

---

<div class="post-metadata">

**Author:** ![gpb01](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gpb01/32/830685_2.png) [@gpb01](https://forum.arduino.cc/u/gpb01)\
**Post date:** [May 10, 2022, 3:13pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/7 "2022-05-10T15:13:30Z")

</div>

> [@mark205](#):
>
> Forse sbaglio a dichiarare la variabile come long?

micro o millis, comunque la variabile deve essere "unsigned long" o "uint32\_t" (_32 bit non segnati_).

---

<div class="post-metadata">

**Author:** ![Z4KK4](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/z4kk4/32/1126465_2.png) [@Z4KK4](https://forum.arduino.cc/u/Z4KK4)\
**Post date:** [May 10, 2022, 4:08pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/8 "2022-05-10T16:08:49Z")

</div>

```cpp
    rpm=60000000/time; //calcolo rpm

```

hai provato ad aggiungere L dopo 60000000 qui ? Una volta impazzì per una svista del genere.

Inoltre la variabile hallstate come mai è int e non bool ?

---

<div class="post-metadata">

**Author:** ![Standardoil](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/standardoil/32/1235732_2.png) [@Standardoil](https://forum.arduino.cc/u/Standardoil)\
**Post date:** [May 10, 2022, 5:08pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/9 "2022-05-10T17:08:32Z")

</div>

> [@mark205](#):
>
> Inoltre il periodo mi esce in millisecondi,

8500 e fischia millisecondi?  
Sono 8 secondi e mezzo  
No, il periodo non ti esce in millisecondi

Inoltre devi considerare anche il tempo di trasmissione...

A 9600 bps sono 1 ms a carattere

Facile che passi più tempo a trasmettere che altro...

---

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 10, 2022, 5:43pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/10 "2022-05-10T17:43:25Z")

</div>

Grazie per le risposte! Provvederò ad aggiornare le variabili.

> [@Standardoil](#):
>
> 8500 e fischia millisecondi?

Hai ragione, non sono millisecondi. La lettura è giusta, avevo sbagliato io il calcolo.

Cercando su internet ho scoperto che il sensore che uso fornisce un segnale digitale “penoso”. All’apertura e chiusura genera un’oscillazione (Lo spiego da ignorante, correggetemi se sbaglio) quindi arduino legge centinaia di passaggi. Con un condensatore e una resistenza dovrei risolvere? E nel caso mi sapete indicare che condensatore e resistenza comprare.

---

<div class="post-metadata">

**Author:** ![brunello22](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/brunello22/32/214773_2.png) [@brunello22](https://forum.arduino.cc/u/brunello22)\
**Post date:** [May 10, 2022, 7:52pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/11 "2022-05-10T19:52:24Z")

</div>

non e' che quel sensore fa schifo, è che si tratta di un sensore lineare e quindi non adatto a quello che vuoi farci tu.  
su quale piedino lo hai collegato A0 o D0 ?

comunque ti conviene usare un sensore digitale.... ad esempio l' A3144

---

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 10, 2022, 9:43pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/12 "2022-05-10T21:43:26Z")

</div>

L’ho collegato a D0. Il venditore lo vendeva come un sensore adatto per il mio scopo. Proverò con un A3144.  
Grazie

---

<div class="post-metadata">

**Author:** ![Datman](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/datman/32/219519_2.png) [@Datman](https://forum.arduino.cc/u/Datman)\
**Post date:** [May 11, 2022, 7:38am UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/13 "2022-05-11T07:38:32Z")

</div>

Per le prove con tutti quei Serial.print credo che ti convenga disattivare l'interrupt in magnete() e riattivarlo dopo l'ultimo Serial.print. In questo modo perderai alcuni impulsi, quindi puoi farlo solo per queste prove.

---

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 14, 2022, 6:53am UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/14 "2022-05-14T06:53:15Z")

</div>

Aggiornamenti: ho cambiato il sensore con un KY-003, il problema delle false letture è stato risolto. Ho corretto il codice con i vostri consigli:

```cpp
#include <StopWatch.h>

const byte led = 12; // bobina
const byte hall = 2; // sensore hall

volatile bool hallstate = HIGH; // stato magnete

StopWatch sw_micros(StopWatch::MICROS); // contatore periodo

uint32_t time = 0; //periodo 
uint32_t rpm = 0; //numero giri

void setup() {
  Serial.begin(9600);                     
  pinMode(led, OUTPUT); //bobina 
  pinMode(hall, INPUT_PULLUP); //pullup sensore
  attachInterrupt(digitalPinToInterrupt(hall), magnete, RISING); //interrupt passaggio magnete
  sw_micros.start(); //inizia a contare periodo
}

void loop(){
  if(hallstate == LOW){
    time=sw_micros.elapsed(); //memorizza periodo
    sw_micros.reset(); //azzera timer periodo
    sw_micros.start(); //riavvia il contatore
    hallstate = HIGH; //reimposta hallstate
    
    scintilla(); //void scintilla
    Serial.println(time); //stampa durata periodo
    Serial.print("\t");
    rpm=60000000/time; //calcolo rpm
    Serial.println(rpm); //stampo rpm
   }
  
} 

void scintilla()
{
  digitalWrite(led, HIGH); //accendi bobina
  delayMicroseconds(1000);
  digitalWrite(led, LOW); //spegni bobina
}

void magnete() 
{
  hallstate = !hallstate ; //passaggio magnete
}

```

---

<div class="post-metadata">

**Author:** ![Datman](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/datman/32/219519_2.png) [@Datman](https://forum.arduino.cc/u/Datman)\
**Post date:** [May 20, 2022, 7:29am UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/15 "2022-05-20T07:29:14Z")

</div>

Anziché legarti a una libreria, però, con poco sforzo puoi usare micros(), semplificando anche il codice. A volte è più facile scrivere il codice direttamente che usare una libreria! 🙂

---

<div class="post-metadata">

**Author:** ![Datman](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/datman/32/219519_2.png) [@Datman](https://forum.arduino.cc/u/Datman)\
**Post date:** [May 20, 2022, 7:58am UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/16 "2022-05-20T07:58:05Z")

</div>

```cpp
uint32_t t0=micros(); // t all'inizio del conteggio

// - loop -
time=micros()-t0; // In realtà non si dovrebbe chiamare time, ma periodo!
t0=micros();

```

---

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 24, 2022, 8:59pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/17 "2022-05-24T20:59:19Z")

</div>

> [@Datman](#):
>
> Anziché legarti a una libreria, però, con poco sforzo puoi usare micros(), semplificando anche il codice. A volte è più facile scrivere il codice direttamente che usare una libreria! 🙂

Avevo pensato anch’io all’inizio di usare micros(), ma mi era venuto il dubbio su cosa potesse succedere se il programma superasse i 70 minuti (circa mi pare) di esecuzione, ossia quando micros si azzera. In teoria avrei un valore di t0 estremamente grande e micros che è praticamente zero, quindi facendo micros()-t0 verrebbe un numero negativo. Ma sempre in teoria uint32\_t non dovrebbe avere segno, quindi 0-(qualsiasi numero) farebbe sempre zero. Giusto? Il periodo però non può essere zero.

---

<div class="post-metadata">

**Author:** ![gpb01](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gpb01/32/830685_2.png) [@gpb01](https://forum.arduino.cc/u/gpb01)\
**Post date:** [May 24, 2022, 9:06pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/18 "2022-05-24T21:06:00Z")

</div>

> [@mark205](#):
>
> Ma sempre in teoria uint32\_t non dovrebbe avere segno, quindi 0-(qualsiasi numero) farebbe sempre zero. Giusto?

Sbagliato ... leggi [questo](https://www.leonardomiliani.com/?p=576) tutorial (_è riferito a millis(), ma è la stessa cosa_) 😉

Guglielmo

---

<div class="post-metadata">

**Author:** ![Maurotec](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/maurotec/32/213982_2.png) [@Maurotec](https://forum.arduino.cc/u/Maurotec)\
**Post date:** [May 24, 2022, 11:34pm UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/19 "2022-05-24T23:34:21Z")

</div>

micros() è internamente usata dalla libreria, forse per questo ti suggerivano di usare micros() direttamente. Per il discorso degli interi senza segno, cioè uint e per esempio uint8\_t.  
Bene uint8\_t è grande 8-bit e con tutti i bit accesi il valore decimale vale 255 (0xff esadecimale).  
Se a 255 ci aggiungi una unità a causa dell'overflow ritorni a 0. L'overflow al contrario lo possiamo chiamare underflow e cioè 0 - 1 = 255. Sperimentali con Serial.println(). Fai attenzione anche alla promozione al tipo int quando si eseguono operazioni su due o più variabili di tipo uint8\_t.  
Occhio che la promozione è legata alla architettura e quindi ad esempio su esp32 la promozione è ad int32\_t. Insomma il C/C++ ti può sorprendere fornendoti risultati non aspettati e quindi sarebbe tra le prime cose da sperimentare.

Ricorda che micros() ha risoluzione di 4us, quindi non otterrai mai 6us. Questo tipo di applicazioni  
dovrebbero essere sviluppate facendo uso dei timer hardware e su arduino UNO ne trovi 3 di cui 2 a 8-bit (timer0 e timer2) e 1 a 16-bit (timer1). Purtroppo usare questi timer richiede la manipolazione dei registi interni mappati in memoria ram dall'indirizzo 0 a 256. Il framework di arduino non è adatto per questo tipo di applicazioni, basti solo pensare che per accendere un pin di una porta bastano 62.5n impiegando i registri, mentre con digitalWrite non ricordo con precisione ma è almeno 20 volte più lento. Classifico questa applicazione tra quelle dove il tempo è critico e infatti si chiamano time-critical. Si può arrivare al punto in cui aggiungi una istruzione e le tempistiche non vengono rispettate e l'applicazione fallisce.

Ad esempio la tua funzione scintilla impegna la cpu (impedendo di fatto di eseguire altro codice nel loop) per 1ms. C'è modo di evitare ciò impiegando i timer che possono essere configurati per generare segnali PWM su alcuni pin.

Scusa il post lungo, ma dovevo avvertirti, con ciò non ti sto dicendo di desistere ma considera  
i limiti delle funzioni facilitate come digitalWrite, read ecc.

Ciao.

---

<div class="post-metadata">

**Author:** ![mark205](https://avatars.discourse-cdn.com/v4/letter/m/a87d85/32.png) [@mark205](https://forum.arduino.cc/u/mark205)\
**Post date:** [May 25, 2022, 7:03am UTC](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325/20 "2022-05-25T07:03:04Z")

</div>

> [@gpb01](#):
>
> Sbagliato ... leggi [questo](https://www.leonardomiliani.com/?p=576) tutorial (_è riferito a millis(), ma è la stessa cosa_) 😉

Grazie, proverò a sperimentare con micros().

> [@Maurotec](#):
>
> Ricorda che micros() ha risoluzione di 4us, quindi non otterrai mai 6us. Questo tipo di applicazioni  
> dovrebbero essere sviluppate facendo uso dei timer hardware e su arduino UNO ne trovi 3 di cui 2 a 8-bit (timer0 e timer2) e 1 a 16-bit (timer1). Purtroppo usare questi timer richiede la manipolazione dei registi interni mappati in memoria ram dall'indirizzo 0 a 256. Il framework di arduino non è adatto per questo tipo di applicazioni, basti solo pensare che per accendere un pin di una porta bastano 62.5n impiegando i registri, mentre con digitalWrite non ricordo con precisione ma è almeno 20 volte più lento. Classifico questa applicazione tra quelle dove il tempo è critico e infatti si chiamano time-critical. Si può arrivare al punto in cui aggiungi una istruzione e le tempistiche non vengono rispettate e l'applicazione fallisce.

Prima di iniziare il progetto mi sono informato sulla velocità di lettura/scrittura di Arduino Uno. Ipotizzando che il mio motore riesca a raggiungere 20000rpm (e non li raggiunge, si ferma attorno ai 13/14000) il periodo è di 3ms, quindi per l’esecuzione del programma dovrei ancora rientrarci alla grande. (Mi sbaglio?) Con una risoluzione di 4us avrei (sempre a 20000rpm) una precisione di mezzo grado, che è più che sufficiente. Inoltre se conosco il ritardo tra il passaggio del magnete e lo scoccare della scintilla dovuto all’esecuzione del programma mi basta spostare il sensore hall in modo da compensare il ritardo. Questo lo verificherò sperimentalmente.

[Next page](https://forum.arduino.cc/t/accensione-elettronica-motore-termico/990325.md?page=2)
