Progetto cambio Kart al Volante

Buongiorno ragazzi, sono nuovo del forum e di Arduino, da circa una settimana sto cercando di progettare il software per pilotare un cambio elettro attuato per il Kart di un amico, premetto inoltre che sto effettuando la programmazione tramite tinkercard in modo virtuale.
Visitando le pagine del forum e spacchettando le varie funzioni da effettuare sono riuscito a far fare al mio programma quasi tutto quello che gli chiedo.
Cerco ora di spiegare al meglio ciò che mi manca:
Ho programmato il tasto per la cambiata in salita ( per quello un scalata penso di utilizzare la stessa funzione), premendo il tasto ho previsto di far effettuare la cambiata senza alzare il pedale dell'acceleratore
quindi includendo nella funzione un sistema di stacco corrente alla candela prima di dare il comando all'attuatore elettromagnetico.
Non riesco però a fare in modo che la funzione ciclica venga svolta completamente senza che il programma non tenga conto della durata dell'impulso del tasto.

Più precisamente vorrei che la scheda, alla pressione del pulsante, legga un solo impulso di alcuni millisecondi.

Potete Aiutarmi?

Grazie

ciao luca3791,

nella tua funzione, o nel tuo codice, stai utilizzando delay()?...cerca "millis() e macchina a stati finiti"...nel forum se ne è parlato tanto.

Provvedo!!

Metti il programma?

ma è affidabile arduino per questo genere di uso?

Come pensi di interrompere quella "leggera" corrente che ha va alla candela? :o
Piuttosto manda a massa come si fa spegnendo il ciao

gianlucaf:
ma è affidabile arduino per questo genere di uso?

NO, ma spero bene che ci faccia solo un prototipo e poi realizzi la board definitiva come si deve !

Guglielmo

Buongiorno a tutti,
come avevo già anticipato sto usando per la programmazione il portale di Tinkercard ( non so se parte dei problemi possano derivare proprio da ciò), e da quel poco che ho capito la programmazione a stati finiti e propria dell'IDE di Arduino?

Gran parte dei problemi però sono sicuramente dovuti alla mia ignoranza. Stamattina ho messo le indicazioni alle varie righe del programma (per come penso debba funzionare) cosi magari lo posto e vedete se è ben scritto.

Ho provato ad eseguire lo sketch sul simulatore di tinkercard, dove sembra funzionare a dovere. Ma provando a variare le variabili di durata degli output mi sembra che i tempi di durata del ciclo di funzione non vari. Potrebbe essere un problema del simulatore?

Acuplush ovviamente si usa il metodo vecchio piaggio x staccare la corrente alla candela. :smiley: :smiley:

gpb01, per board intendi il circuito stampato dove andrò a sistemare le componenti elettroniche o proprio Arduino non è indicato? Avevo pensato di disporre mosfet e resistenze su un circuito stampato.

const int CutOff = 4;               //definisco costante CutOff per comando stacca bobina al cambio marcia sul pin4
const int buttonUp = 2;           //definosco costante buttonUp per pulsante Marcia Sup al pin 2
const int GearUp = 5;             //definisco costante GearUp comando attuatore elettromagnetico  per marcia sup al pin5 
int val = 0;                             //assegno alla variabile val valore 0
int vecchioVal = 0;                  //assegno alla variabile vecchival valore 0
int stato = 0;                          //assegno alla variabile stato valore 0

unsigned long CutOffTime;        //definisco la variabile cutoftime
unsigned long GearUpTime;      //definisco la variabile gearuptime
bool CutOffOn;                        //definisco la condizione vero falso cutoffon
bool GearUpOn;                       //definisco la condizione vero falso gearupon

void setup(){
 pinMode(CutOff, OUTPUT);       // assegno al pin4 valore di output 
 pinMode(GearUp, OUTPUT);      //assegno  al pin5 valore di output
 pinMode(buttonUp, INPUT);      //assegno al pin 2 valore di imput
 
 CutOffOn = false;                    //assegno a cutoffon la condizione falso
 GearUpOn = false;                   //assegno a gearupon la consizione falso
}

void loop(){ //funzione ciclica
 val = digitalRead(buttonUp);                                //associa la variabile val  al valore del input al pin2
 if ((val == HIGH) && (vecchioVal == LOW)){        //SE si verifica la condizione che val assume valore 1 e vecchival 
                                                                             valore 0
   stato = 1;                                                       //la veriabile stato passa a valore 1
 }
  vecchioVal = val;                                              //vecchioval assume il valore di val
 if (stato == 1){                                                 //Se si verifica la condizione che la variabile stato prende valore 1
   digitalWrite(CutOff, HIGH);                               //attiva output cutoff al pin4
   CutOffOn = true;                                              //associa la condizione vero a cutoffon
   CutOffTime = millis();                                       //la variabile cutofftime prende il valore dei millisecondi
   delay (90);                                                       //blocco la funzione per 90 millisec (il cutoff candela deve anticipare 
                                                                             l'elettroattuatore
   digitalWrite(GearUp, HIGH);                              //attiva output gearup al pin5
   GearUpOn = true;                                             //associa la condizione vero a gearupon
   GearUpTime = millis();                                      //la variabile gearupon prende il valore dei millisecondi
  
   if (CutOffOn, true)                               //al verificarsi del valore vero della variabile cutoffon
     if (millis() - CutOffTime >70)              //    se verifica che il valore della sottrazione tra millis
     digitalWrite (CutOff, LOW);                 //    e cutofftime è maggiore di 70 millisec disattiva l output CutOff 
     CutOffOn = false;                               //    associa a CutOffOn valore falso
   }
   if (GearUpOn, true)                            //al verificarsi del valore vero della variabile GearUpOn
     if (millis() - GearUpTime >150){       //    se verifica che il valore della sottrazione tra millis
     digitalWrite (GearUp, LOW);             //    e GearUpTime è maggiore di 150 millisec disattiva l output GearUp 
     GearUpOn = false;                           //    associa a GearUpOn valore falso
   }  
 }
 else {                                                 //altrimenti mantiene i due output CutOff e GearUp disattivati
   digitalWrite(CutOff, LOW);
   digitalWrite(GearUp, LOW);
 }
 stato = 0;                                           //riporta la variablie stato 0
}

Va meglio?

Scusate e Grazie

luca3791:
come avevo già anticipato sto usando per la programmazione il portale di Tinkercard ( non so se parte dei problemi possano derivare proprio da ciò)

Beh, primo, su Tinkercad devi considerare che per qualche arcano motivo (non me lo spiego perché abbiano fatto così) la funzione millis() non restituisce il valore in millisecondi ma in CENTESIMI di secondo. Quindi millis()-startMillis = 100 significa che è trascorso un secondo e non 1 decimo. Questo va considerato sempre in quel simulatore altrimenti tutti i timer sballano.
EDIT: mi correggo, hanno sistemato questa cosa, scusate per l'imprecisione ma era tempo che non andavo su Tinkercad e ricordo che fin dai tempi di 123circuits c'era sta cosa idiota. :slight_smile:

Secondo, ma non meno importante, prima che un moderatore si incazzi, non devi incollare il codice ma devi racchiuderlo nei tag [ code ] (vai in modifica con "More..." "Modify", seleziona il codice, quindi clicca sul pulsantino [/] che vedi in alto a sinistra nell'editor).

Quando avrai fatto questo, potremo iniziare a parlare del codice.

>luca3791: come già ti ha detto "docdoc", ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

Ho modificato il messaggio, spero che ora vada meglio!!

Qui non ci siamo

 if (CutOffOn, true)

La if non lavora così
Da altre parti la hai usata bene...

Consiglio: semplificati molto
E per le prime prove Usa delay, quando cominci a vedere risultati passa a millis
Che comunque strettamente non serve, tanto fai una sola cambiata per volta
Inoltre: metti commenti più concisi ma più significativi

GearUpOn = true;                                             //associa la condizione vero a gearupon

lo vediamo tutti che assegna vero, quello che non vediamo semmai è cosa sia gearupon

Ciao Karma,
i commenti li avevo messi prima di tutto per me per cercare di rammentare in maniera elementare la logica dello sketch, sono stato talmente bravo che effettivamente ho tralasciato di descrivere CutOffon e gearUpOn che sono la condizione del mosfet per lo stacco corrente e dell'elettroattuatore del cambio (non so se effettivamente serva scriverle ma comunque il programmino gira).

Mi puoi specificare meglio perche la If non funziona cosi?

Avevo provato all'inizio con delay ma se rimanevo con il pulsante di marcia su pigiato la funzione ciclica si interrompeva fino al rilascio del pulsante.

Comunque oggi ho caricato il programma sulla scheda domani provo a vedere se con la scheda i tempi di esecuzione sono esatti.

Grazie

luca3791:
Mi puoi specificare meglio perche la If non funziona cosi?

Perché "if (CutOffOn, true)" non è una sintassi corretta, è sempre valutato true.
Devi mettere una condizione booleana come:

if (CutOffOn == true)

oppure più semplicemente:

if (CutOffOn)

Buonasera,
ho cercato di seguire i vostri consigli, cercando di semplificare quanto possibile, usando il delay ed infine ho cercato di suddividere la funzione con gli stati finiti.

Per il momento ho suddivisogli stati così:

case 1: passaggio a marcia superiore
caso 2: passaggio a marcia inferiore

Per il secondo sono riuscito ad usare il comando delay ed è venuto un lavoro pulito

Per il primo invece dato che devo azionare due output ed in momenti diversi ho provato a riportare i comandi che avevo scritto nel precedente sketch ma non riesco a farlo funzionare e non riesco a capire qual'è il problema.

posto qui sotto lo sketch potreste aiutarmi?

int stato = 1; //variabile che sposta il void loop nei 2 stati che ho creato
int val = 0; // variabile che prende il valore del pulsante collegato al pin 2 e che comanda le marce in salita
int val2 = 0; //variabile che prende il valore del pulsante collegato al pin 3 e che comanda le marce in scalata
int vecchioVal = 0; // memorizza il valore precedente del pulsante al pin2
int vecchioVal2 = 0; // memorizza il valore precedente del pulsante al pin3
int stac = 0; //QUI CASCA L'ASINO senza questa variabile scopiazzata il pin2 viene letto solo una volta
int stac2 = 0; //QUI RICASCA L'ASINO senza questa variabile scopiazzata il pin3 viene letto solo una volta

unsigned long led1Time; //millisec di attivazione output pin11
unsigned long led2Time; //millisec di attivazione output pin12

bool led1On;
bool led2On;

void setup(){     //assegno ingressi ed uscite
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  
  led1On == false;         //condizione stato led
  led2On == false;
}

void loop(){
  
    
  switch (stato){
    case 1: //in questo stato o case1  devo accendere al led pin 11(simula stacco bobina)
    val = digitalRead(2);
    if ((val == HIGH) && (vecchioVal == LOW)){
     stac = 1 - stac;
      vecchioVal = val;
    if (stac = 1){
      digitalWrite(11, HIGH);
      led1On == true;
      led1Time = millis();
      delay (90); //bloccare per 90 millisec l esecuzione del loop
      digitalWrite(12, HIGH); //accendere il led al pin 12(simula attuatore marcia su)
      led2On == true;
      led2Time = millis(); //registra millisec attivazione pin12
   
      if (millis() - led1Time > 150){ //disattiva pin 11 dopo 150 millisec
      digitalWrite(11, LOW);
      led1On == false;}
   
      if (millis() - led2Time > 300){ //disattiva pin 12 dopo 300 millisec
      digitalWrite (12, LOW);
      led2On == false;
     stac = 0;
        stato = 2; //NELLE MIE INTENZIONI passa al case 2 
      }
    }
    }
    else { //se non agisco sui pulsanti SEMPRE 
    digitalWrite(11, LOW); //  NELLE MIE INTENZIONI passa al case 2
    digitalWrite(12, LOW);
      stato = 2;
      break;
      
    }
    case 2:   //stato o case 2 per le marce in scalata
    val2 = digitalRead(3);   // prende valore pulsante al pin3
    if((val2 == HIGH) && (vecchioVal2 == LOW)){   // se verifica un cambio di stato delle variabile
      stac2 = 1 - stac2;
      if (stac2 = 1) 
    digitalWrite(13, HIGH);          //accende led al pin 13(simula attuatore marcia giù
    delay (150);
      stac2=0;
      stato = 1;   // NELLE MIE INTENZIONI passa a stato o case 1
    }
  else {          // se non agisco sui pulsanti torna a stato o case 1
    digitalWrite(13, LOW);
    break;
  }
     stato = 1;
  }
}

Grazie

luca3791:
.
.
.

posto qui sotto lo sketch potreste aiutarmi?

  led1On == false;         //condizione stato led

led2On == false;





Grazie

ti consiglio fortemente di leggersi bene un buon libro di 'C', questo errore è indice che non hai proprio assimilato la "grammatica" del 'C'

dopo ti posto un esempio di programma "mio"

Ok, fatto un prototipo
dovrebbe andare (di fatto son convinto che andrà)
ti ho fatto solo la marcia a salire, non quella a scendere

// di Nelson "StandardOil"
// Idea da sviluppare:
// cambiata assistita

// configurazione piedini
byte p = 2; // comando a salire
byte m = 3; // comando a scendere

byte g = 13; // marcia giu
byte s = 12; // marcia su
byte b = 11; // interdizione bobina

#define MARCE 5 // numero massimo di marce
byte marcia = 0; // marcia attuale

#define T1 150 // tempo in millisecondi per toglire accensione
#define T2 300 // tempo in millisecondi per marcia su
#define T3 300 // tempo in millisecondi per marcia giu

void setup(void)
{
    pinMode(p, INPUT);
    pinMode(m, INPUT);
    pinMode(g, OUTPUT);
    pinMode(s, OUTPUT);
    pinMode(b, OUTPUT);
}

void loop(void)
{
    if (digitalRead(p))
    {
        // non serve un de-bounce software
        // il tempo di bounce è certamente MOLTO minore del tempo di cambiata
        // NON è possibile che prenda due cambiate di seguito per sbaglio
        // cambiare è semplice
        // se NON siamo già in ultima marcia
        if (marcia < MARCE)
        {
            // togliamo accensione
            digitalWrite(b, HIGH);
            delay(T1);
            // attesa che il motore esca di coppia causa accensione inibita
            // non serve usare millis(), duranta la cambiata NON puoi fare altro che aspettare
            // avviare attuatore
            digitalWrite(s, HIGH);
            delay(T2);
            // OK atteso tempo sufficente per la cambiata a salire
            // fermo l'attuatore
            digitalWrite(s, LOW);
            // rido' potenza
            digitalWrite(b, LOW);
            // aggiorno la marcia attuale
            marcia++;
        }

        // adesso, per evitare false manovre deve sentire pulsante rilasciato
        while (digitalRead(p));

        // e per finire un tempo di inibizione per assicurarsi il de-bounce finale del tasto
        delay(15);
    }


}

noterai che la sua complessità ciclomatica è scarsa, in particolare rispetto al tuo programma
non è nemmeno tanto lungo, e compila in 1352 byte con 10 byte di variabili (sto parlandeo della verione completa, con anche il comando di scalata, che sono sicuro sarai in grado di aggiungere tu
la versione che ti ho postato compila in 1284 byte e 10 di variabili, insomma un'inezia
megaconsiglione:
pianifica meglio le operazioni, che viene tutto più facile

Buongiorno Standardoil,

grazie ai tuoi preziosi consigli e suggerimenti, sono riuscito a terminare il programma.
Come ripeto sono veramente alle prime armi, ho visto quanto è importante (oltre alla grammatica) la
pianificazione del progetto.

Nei post precedenti si paventava di una non affidabilità della scheda arduino per questi progetti, tale difetto è legato solo all'instabilità dei collegamenti pin o proprio agli standard dell'arduino?

Grazie a tutti del tempo dedicatomi.

luca3791:
Nei post precedenti si paventava di una non affidabilità della scheda arduino per questi progetti...

... prova a rileggere il REGOLAMENTO, punto 15.5 ... ci sono già li le spiegazioni forndamentali a cui ... se ne aggiungono molte altre. :wink:

Guglielmo

gpb01:
... prova a rileggere il REGOLAMENTO, punto 15.5 ... ci sono già li le spiegazioni forndamentali a cui ... se ne aggiungono molte altre. :wink:

Guglielmo

un chiarimento curiosità, se sai, sarebbe possibile certificare un prodotto commerciale fatto con arduino?
Ovvero qualcuno fa prodotti per domotica/industriale con arduino?
Oppure l'hardware non ha proprio i requisiti per essere certificabile?