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.
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.
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
}
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.
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.
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.
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;
}
}
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
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?
gpb01:
... prova a rileggere il REGOLAMENTO, punto 15.5 ... ci sono già li le spiegazioni forndamentali a cui ... se ne aggiungono molte altre.
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?