Cambio elettronico: sequenziale/automatico

Salve a tutti.
Nuovo utente (ogni volta che mi iscrivo ad un forum lo faccio dopo aver letto mezza pagina, sia chiaro)

Ho deciso di iscrivermi perché ho iniziato i miei primi passi nel mondo di arduino e vorrei esporre qui i piccoli risultati che conseguirò, oltre a qualche quesito.

NB. Siccome sono un po' strano (ho la sindrome di asperger) se dovessero notarsi atteggiamenti che giudicate strani, chiedo di non fermarsi alle apparenze traendo conclusioni affrettate.

Il progetto su cui sto lavorando attualmente è un cambio automatico per la mia futura bici a pedalata assistita.

Lo schema circuitale (se si chiama così) l'ho realizzato sfruttando lo strumento di configurazione del sito circuito.io
E lo si può consultare attraverso questo link
https://www.circuito.io/app?components=514,11022,9239,9239,305155,305155,305155,305155,305155,305155,9312,9312,9312

Ora viene il brutto: scrivere il programma.
La logica non mi è un problema, ma la sintassi decisamente si.

Memore di una prima infarinatura di C accantonata nel 2013 in un tentativo universitario arenatosi miseramente sugli scogli del lavoro a tempo pieno in ambiente sanitario e su turni in quinta, qualcosa lo rammento...

Se riesco a far funzionare sto aggeggio sarà una grandiosa, epocale botta d'autostima!

Spiegando i vari componenti:
1 userò effettivamente un arduino nano v.3
2 al posto degli easydriver ho deciso di usare 2 A4988
3 i motori passo passo sono invece degli "anonimi" JSDJ2P4W8L dovrebbero lavorare tra 3-5V ma tanto costano 50cent e se si dovessero bruciare a causa della sovratensione a 8v proveniente dagli a4988 che userò, potrò decidere di optare per 2 nuovi motori oppure per gli stessi ma con dei resistori in serie ad ogni pin.
4 i tre sensori hall li utilizzerò per rilevare la velocità della bici, e la velocità e direzione di pedalata della pedivella sinistra
5 i microinterruttori li userò per:
5a 2 microinterruttori come fine corsa per il deragliatore anteriore, se entrambi disattivi il deragliatore sarà sulla corona centrale.
5b 4 microinterruttori per il deragliatore posteriore a formare una sorta di sensore di posizione con una piastrina con punzoni posti in sequenza binaria da 0001 a 1001 (sul pignone ho 9 corone).
Se a tal merito, qualcuno mi volesse consigliare qualcosa di meno spartano, sarà ben accetto.

Ho ordinato tutto il necessario e anche un po' di più.
Dato che viene tutto dalla Cina, tornerò a scrivere tra 2 mesi o, se PosteItaliane si degna di portarmi la roba in tempi umani dal momento in cui arriva in Italia, anche prima.

Se la logica di come deve funzionare il programma non è un problema, allora posta un diagramma di flusso, o un qualsiasi altro metodo di tua conoscenza, che la descriva in passi elementari. Questo significa partire da un progetto che rappresenta esattamente ciò che vuoi fare, così ottieni due obiettivi: rendi chiaro a te stesso e - si spera - agli altri lo scopo del programma da realizzare e contestualmente l'attività di programmazione diventa una mera traduzione della logica in istruzioni del generico linguaggio di programmazione impiegato.

Grazie del consiglio
Ho appena terminato la realizzazione del diagramma di flusso, disponibile in allegato.

Il diagramma che hai fatto è un buon inizio, tuttavia sarebbe meglio se lo rifacessi utilizzando i simboli standardizzati dei diagrammi di flusso (ellisse, rombo, rettangolo) per permettere una maggiore comprensione a chi lo legge. Inoltre dovresti rendere più chiare le linee di flusso tramite delle frecce entranti/uscenti dai blocchi e le indicazioni "sì/no" / "vero/falso" a valle dei blocchi di selezione, al fine di esplicitare il risultato della scelta effettuta nel programma al verificarsi della condizione testata.

Prova a leggere questa guida sui diagrammi di flusso (flow chart):
flow_chart

Cerca di strutturare il diagramma seguendo scrupolosamente le regole di "sequenza, selezione, iterazione (ciclo)".

Per semplificare la stesura, e l'eventuale modifica futura, del diagramma di flusso ti consiglio di utilizzare il programma Dia. Il vantaggio di questo programma è che ti permette di salvare il diagramma fatto in un formato di file, diciamo sorgente, .dia. Se successivamente riapri il file .dia puoi modificarlo in ogni sua parte e spostare gli elementi disegnati come la prima volta che l'hai composto, non si crea un'immagine statica. Puoi anche riutilizzare le tabelle dell'altro diagramma che avevi fatto tramite la funzione di aggiunta immagine.

Link per scaricare il programma:

Il Big EASYDRIVER monta il A4988.
Se il motore passo passo ha come tensione nominaler 5V allora 8V sono troppo pochi per farlo funzionare bene in pilotaggio in corrente a mirostep. Ne hai bisogno qualcosa come 20V. Il valore non é critico perché il A4988 limita la corrente e la tensione dipende dall indutanza del avolgimento. Comunque se alimenti il triver con uan tensione molto piú alta non rompi il motore perche questo riceve solo la corrente impostata sul A4988.

Ci fai vedere il link al motore che usi per trovare un datasheet.

Ciao Uwe

Ho cercato ripetutamente per giorni il datasheet del motore passo-passo ma l'unica cosa che ho trovato è sempre lo stesso annuncio su aliexpress.

Se cercate questa sigla su google JSD2P48L troverete tanti risultati per la stragrande maggioranza connessi a questo annuncio
https://www.aliexpress.com/snapshot/0.html?spm=a2g0s.9042311.0.0.54474c4dDGOb1l&orderId=506062897156816&productId=32799694360

In annunci connessi di motori molto similari ho appurato il range di tensione di lavoro.

Oggi sono in viaggio, partito alle 6:50 torno stasera alle 20 e mi metto a fare il diagramma di flusso come da regola.
Grazie per la partecipazione ed i consigli.

https://it.aliexpress.com/item/2PCS-lot-2-Phase-4-Wire-Stepper-Motor-with-Precision-Long-rod-8-34-8mm-Mini/32799694360.html

Ti sconsiglio vivamente quel motore.
Dalle foto vedo che ha una barra filetata ma non ha un dado che si muove sulla barra filetata. Non so come potresti agganciare il cambio al motore. Ha pochissima forza visto che é fatto per muovere la testina di un lettore CD/DVD ed non é adatto col uso con un A3967 o A4988

Non so consigliarti quale motore potrebbe andare bene non sapendo precisamente la meccanica che usi o voui usare o Ti costruisci.

Ciao Uwe

Chiarisco che ho preso il più economico motore passo-passo dotato di una barra filettata che ho trovato.
La meccanica:
La piastrina la taglio così posso inserire il dado.
Quanto alla forza:
Il deragliatore non necessita di grande forza per essere azionato.
Così come appare di fabbrica è duro da azionare per via della molla di ritorno.
Togliendo la molla, risulta libero di muoversi.
Se poi il motore non è comunque sufficientemente potente per azionare il deragliatore, opterò per un altro motore.
Per la meccanica mi adatto, non ho grossi problemi da quel punto di vista.
Ho scelto questo con la barra filettata solo perché era molto contenuto in diametro e perche mi evitava di usare un giunto con cui accoppiare una barra filettata con l'asse del motore.
In teoria potrei anche adottare un motore con una ruota dentata sull'asse, una cremagliera con una barra laterale provvista di una scanalatura in cui inserire la parte terminale dell'albero motore, così da tenere la ruota dentata ben premuta sulla cremagliera.
La cremagliera sarebbe semplicemente incernierata al deragliatore.
Certo si produrrebbe lo spiacevole problema di un movimento non proprio fluido del motore, per questo avevo scelto la barra filettata.

Riscrivo appena termino il diagramma di flusso fatto come si deve.

Sei consapevole che quel motore ha una barra filettata un po piú lunga di 2 cm e se metti un dado Ti restano una corsa meno di 1,5cm? Il diametro della barra filetata é di 2mm.

Ciao Uwe

con quel motore non lo muovi proprio il deragliatore di una bici, ho provato ad utilizzare qualcuno simile recuperato da un lettore cd e davvero hanno appena la forza per spostare la testina laser :confused:

Torno a scrivere stasera.
la realizzazione del diagramma di flusso è quasi completa ma non del tutto e per stasera, dopo 7 ore che ci lavoro ininterrotte, direi che può bastare.

Lo fornisco in allegato anche se è da finire, almeno ci date un'occhiata e mi dite se è un gran casino oppure c'è del buono ma da rifinire.

Ho appurato dai vari interventi, che il motore che avevo scelto non è assolutamente adatto.

Poco male, perché mi sono ricordato di avere una stampante 3D reprap Huxley con l'atmega bruciato da cui prelevare pezzi...

Ci sono quei bei motori NEMA (non vorrei sbagliare ma a memoria mi sembra siano da 35-40mm di diametro) che fanno proprio al caso mio.
Ci sono anche gli accoppiatori flessibili.
Quindi non ho che da attendere l'arrivo degli altri componenti che ho ordinato.

In allegato la bozza del diagramma di flusso.

Add: vedo che non è possibile allegarlo come file.
Risolto: fornisco link di download dal mio cloud
https://1drv.ms/u/s!AitQSdjMos0Lh78MGimEZvMkd5pBvA

Add: Per ciò che riguarda la meccanica, prendo spunto dalla reprap, un dado stretto in un alloggiamento di plastica o ancora meglio di alluminio, e l'alloggiamento incernierato al deragliatore in un punto il possibile prossimo ai suoi cardini.
La barra filettata sarà di ottone così non c'è problema per gli agenti atmosferici.

Ps. Se il diagramma di flusso è adeguato: Quale è il passo successivo?

uwefed:
Sei consapevole che quel motore ha una barra filettata un po piú lunga di 2 cm e se metti un dado Ti restano una corsa meno di 1,5cm? Il diametro della barra filetata é di 2mm.

Ciao Uwe

Ho risolto, prendo due motori passo passo da una stampante 3D con la CPU bruciata.

Nel complesso il diagramma direi che è fatto bene. Il passo successivo è la programmazione nell'ambiente Arduino, da definire per gradi siccome non hai molta esperienza (come me d'altronde :D).

Io proverei a partire con quest'ordine di azioni:

1- Definizione delle variabili da usare nel progetto, con l'accortezza di usare il più possibile variabili locali. Le variabili globali sono da usare con parsimonia. In generale le costanti devono essere variabili globali, idem il numero di PIN degli input/output di Arduino, e in casi estremi delle variabili che necessitano di essere scritte da qualsiasi parte del programma - ad esempio uno stop di emergenza.
Tendi a definire le variabili nella parte inziale di una funzione (compresa la loop), anche se il C++ permetterebbe di definirle in qualsiasi punto del listato, manterrei le convenzioni del C.
Attenzione a individuare il corretto tipo della variabile nella definizione della stessa, ad esempio se la variabile è binaria (decisione sì/no) sceglierai il tipo bool, se invece può contenere valori interi positivi/negativi userai il tipo int, se è con la virgola il tipo float e così via ... il discorso è lungo.

2- Traduzione in codice dei blocchi del diagramma di flusso. Detto in soldoni, si deve far in modo che il codice sia una scrittura in un'altra forma, comprensibile ad Arduino, dei blocchi grafici.

Per far questo ti consiglio la lettura dei seguenti documenti:

Selezione.pdf
Cicli.pdf

Se ti interessa l'intero corso, che secondo me è molto valido, lo trovi a questo indirizzo:
http://staff.polito.it/claudio.fornaro/CorsoC/

Quindi tenendo quei documenti come riferimento sotto (magari stampali), confronti l'equivalenza fra i tuoi blocchi grafici ed una struttura elementare del C (if-else, while, ecc.). Cioè suddividi il tuo diagramma di flusso in sezioni che si riconducono 1:1 alle strutture anzidette e le scrivi nel corrispondente codice.

Esempio veloce:

In un'altra discussione del forum avevo trattato in maniera più estesa questo argomento e altri che ti possono tornare utili nel tuo progetto (solo pagina 1): realizzazione di un ascensore a 3 piani

3- Dopo una prima stesura provvisoria del programma, ti consiglio di provarlo a pezzi, in modo da varificare dove funziona bene e dove no. Puoi usare delle attese fra gli spezzoni del codice sotto test, fare dei salti alla vecchia con l'istruzione goto, o condizionare l'avanzamento fra uno spezzone e l'altro alla pressione di un tasto che ti abilita l'esecuzione dello spezzone successivo. Il monitor seriale di Arduino per esempio può essere un ottimo aiuto in fase di debug, se memorizzi i risultati intermedi del programma in variabili temporanee che vengono stampate su console mano a mano che il programma viene eseguito. Vedi tu quale metodologia usare, ce ne sono tante altre possibili, in ogni caso fai sempre numerosi backup quando apporti grosse modifiche oppure se introduci dei test.

edit: tieni presente che la mia analisi è di massima e ci sono tanti passaggi intermedi nel mezzo. Ci possono volere dei giorni o delle settimane per fare un programma che funziona (funzionicchia).
Ho modificato l'immagine di esempio per renderla coerente con la condizione del tuo blocco if-else.

ok questo impiegherà parecchio perché dovrò studiare un bel po' di roba.

Grazie!

Ps. Curioso che il Kr abbia aiutato il XeF6 :slight_smile:

Add#1:
Ho deciso di modificare il diagramma di flusso ed il set di microswitch portandolo a 4, 2 per deragliatore.
Riduco inoltre a 2 i sensori a effetto hall.
Così ho la possibilità di aggiungere i due pulsanti sul manubrio e restare nel limite dei 10 input.

Per controllare su quale corona o rapporto si trovi il deragliatore uso un microswitch per una corona o rapporto estremi e l'altro per identificare il raggiungimento di ogni stop, soluzione adottata per scongiurare il rischio di errati posizionamenti determinati da perdite di passi da parte del motore passo-passo a causa di possibili ritardi di deragliamento e reinstradamento della catena.

Sto inoltre valutando l'ipotesi di posizionare il motore in modo complanare alla rotazione da imprimere al deragliatore in modo da poter trasferire la rotazione con accoppiamento di semplici ingranaggi, mi sorge tuttavia il dubbio di possibili spostamenti del deragliatore a causa di un'eventuale ridotta inerzia del motore o di sgranamenti tra gli ingranaggi per eventuali flessioni di assi del deragliatore.
Valuterò non appena avrò tutti i pezzi sotto mano ed inizierò ad assemblare.

L'attesa dovuta a poste italiane è snervante... :frowning:

Il programma sarà invece una bella sfida di trascendenza...
Ho fatto veri tentativi ieri ma oltre l'inizializzazione e dichiarazione di una costante matrice15*3 poi risultata inutile, non sono riuscito ad andare.
La sintassi è tostissima da farmi entrare in testa!

...in cerca di sorgenti da cui fare selvaggi copia-incolla...

krypton18:
Se ti interessa l'intero corso, che secondo me è molto valido, lo trovi a questo indirizzo:
Corso di programmazione in C (Standard C89)

Non male, ho aggiunto il "link" hai thread dei "Link Utili" che si trova in "Megatopic" :slight_smile:

Grazie per l'indicazione.

Guglielmo

Sfruttando il progetto di sketch preimpostato che viene prodotto dal sito Circuit.io al seguente indirizzo
https://circuito.io/app?components=514,305155,305155,305155,305155,9312,9238,9238,9312,97,97,11022,1671987,166716
Ho realizzato la void setup()
L'ide compila senza errori salvo per la stringa finale che ho aggiunto tutta in maiuscolo e che mi serve come appunto per riprendere il lavoro di conversione dell'algoritmo in codice di programmazione.

di seguito il sorgente...

Ditemi se ritenete opportuno applicare modifiche.

// Include Libraries
#include "Arduino.h"
#include "HallU1881.h"
#include "SD.h"
#include "StepperMotor.h"
#include <SPI.h>

// Pin Definitions
#define HALLU_1_PIN1_PIN_VOUT 2
#define HALLU_2_PIN2_PIN_VOUT 3
#define MICROSWITCH_1_PIN1_PIN_COM 4
#define MICROSWITCH_2_PIN2_PIN_COM 5
#define MICROSWITCH_3_PIN3_PIN_COM 6
#define MICROSWITCH_4_PIN4_PIN_COM 7
#define PUSHBUTTON_1_PIN1_PIN_2 8
#define PUSHBUTTON_2_PIN2_PIN_2 9
#define SDFILE_PIN_CS 10
#define SLIDESWITCH_PIN_2 A0
#define STEPPER_1_PIN_STEP A2
#define STEPPER_1_PIN_DIR A1
#define STEPPER_2_PIN_STEP A4
#define STEPPER_2_PIN_DIR A3

// Global variables and defines
#define stepper_1DelayTime  1000
#define stepper_2DelayTime  1000
// object initialization
File sdFile;
StepperMotor stepper_1(STEPPER_1_PIN_STEP,STEPPER_1_PIN_DIR);
StepperMotor stepper_2(STEPPER_2_PIN_STEP,STEPPER_2_PIN_DIR);
HallU1881 hallU_1(HALLU_1_PIN1_PIN_VOUT);
HallU1881 hallU_2(HALLU_2_PIN2_PIN_VOUT);
Button microSwitch_1(MICROSWITCH_1_PIN1_PIN_COM);
Button microSwitch_2(MICROSWITCH_2_PIN2_PIN_COM);
Button microSwitch_3(MICROSWITCH_3_PIN3_PIN_COM);
Button microSwitch_4(MICROSWITCH_4_PIN4_PIN_COM);
Button pushButton_1(PUSHBUTTON_1_PIN1_PIN_2);
Button pushButton_2(PUSHBUTTON_2_PIN2_PIN_2);

// define vars for testing menu
const int timeout = 10000;       //define timeout of 10 sec
char menuOption = 0;
String temp;
long time0;
int i;
String j;
bool finecorsa1, finecorsa2, finecorsa3, finecorsa4; 
bool pulsante1, pulsante2;
bool interruttore;
int corona_innestata, corona_innestare;
int rapporto_innestato, rapporto_innestare;


// Setup the essentials for your circuit to work. It runs first every time your circuit is powered with electricity.
void setup() 
{
  // Setup Serial which is useful for debugging
  // Use the Serial Monitor to view printed messages
  Serial.begin(9600);
  while (!Serial) ; // wait for serial port to connect. Needed for native USB
  Serial.println("start");
    
  microSwitch_1.init();
  microSwitch_2.init();
  microSwitch_3.init();
  microSwitch_4.init();
  pushButton_1.init();
  pushButton_2.init();
  // Set SPI SS pin to output otherwise the SD library functions will not work.
  // The SD is set to use SPI SS Arduino pin 10 as chip select(CS) by default.
  // To change the pin use SD.begin(SD_CS_PIN)
  pinMode(SDFILE_PIN_CS, OUTPUT);
    
  // Check if the card is present and can be initialized
  if (!SD.begin()) {
      Serial.println(F("Card failed, or not present"));
      while(1);
  }
  Serial.println(F("card initialized."));
  // enable the stepper motor, use .disable() to disable the motor
  stepper_1.enable();
  // set stepper motor speed by changing the delay value, the higher the delay the slower the motor will turn
  stepper_1.setStepDelay(stepper_1DelayTime);
  // enable the stepper motor, use .disable() to disable the motor
  stepper_2.enable();
  // set stepper motor speed by changing the delay value, the higher the delay the slower the motor will turn
  stepper_2.setStepDelay(stepper_2DelayTime);
  //menuOption = menu();
  sdFile = SD.open("marcia_innestata.txt");
  if(sdFile==true)
  {
    Serial.println("file trovato, inizio lettura");
    while (sdFile.available())
    {
      j = sdFile.readString();
      Serial.print(rapporto_innestato = atoi(j.c_str()));
    }
  }
  else {
    Serial.println("file assente, verrà creato");
    sdFile = SD.open("rapporto_innestato.txt",FILE_WRITE);
    sdFile.write("1");
    Serial.print(rapporto_innestato = atoi(j.c_str()));
    sdFile.close();
  }
}

// Main logic of your circuit. It defines the interaction between the components you selected. After setup, it runs over and over again, in an eternal loop.
void loop() 
{
  temp += String(rapporto_innestato);
  sdFile = SD.open("rapporto_innestato.txt",FILE_WRITE);
  sdFile.print(temp);
  SCOPRIRE COME COLLEGARE INDICARE CON VARIABILE, ATTIVAZIONE SENSORE
}

Si, sto scrivendo tutto il programma senza testare ogni funzione e questo mi creerà tanti problemi di debug, ma non avrò tutti i componenti del cambio prima di 1 mese e mezzo o più...
Quindi adesso mi rinfresco la memoria con la sintassi...
Se poi scrivo della roba salvabile, meglio.

Secondo me ti converrebbe scrivere il codice "parzialmente" da zero. Mi spiego meglio. I nomi delle variabili è importante che siano "parlanti" ed abbiano un significato per te, i nomi generati automaticamente o fatti male portano confusione e in caso di problemi si diventa pazzi a capire cosa sono e cosa fanno in una determinata porzione di programma. La libreria #include "HallU1881.h" l'ho cercata e non sono stato in grado di trovarla, ergo non esiste e all'atto della (tentata) compilazione ti verrà segnalato un errore che impedisce di eseguirla. Con il termine "parzialmente" voglio anche dire che ti conviene fare ricerche mirate su Google del tipo "gestione SD Arduino shield xy" o "utilizzo sensori hall" al fine di imparare da esempi concreti e testati come si configura/programma qualcosa. Ricerche di questo genere inoltre ti fanno capire di che librerie hai veramente bisogno, evitando di aumentare vertiginosamente l'occupazione di memoria del tuo progetto. Tieni presente che con Arduino la memoria può essere un limite se il programma è esteso quel che basta da sforare i limiti, in certe circostanze molto stringenti.

Un consiglio personale per quel che concerne la libreria di debouncing (anti-rimbalzo dei contatti elettromeccanici: pulsanti e microswitch) è di usare la libreria bounce2.

La libreria bounce2 la puoi scaricare direttamente dall'IDE di Arduino: apri il menu Sketch --> seleziona #include libreria --> click su Gestione Librerie... --> nella casella di ricerca scrivi "Bounce 2" --> seleziona l'ultima versione disponile e poi fai click su "installa"

Un esempio d'uso della libreria e degli array, lo trovi fra i programmi di esempio della libreria bounce2 a questo indirizzo:

https://github.com/thomasfredericks/Bounce2/blob/master/examples/bounce_multiple/bounce_multiple.ino

Gli array ti serviranno per raggruppare gli ingressi dei pulsanti e dei microswitch in aree di memoria contigue con lo scopo di renderli di più facile gestione dalle funzioni di lettura di bounce2.

Esempio di definizione di un array:

const uint8_t FINECORSA[] = {2, 3, 4, 5, 6, 7, 8, 9};

const uint8_t NUM_FINECORSA = sizeof(FINECORSA) / sizeof(FINECORSA[0]); //ricavo il n° di finecorsa definiti (ovvero il numero di elementi dell'array FINECORSA)

La libreria HallU1881.h l'ho trovata nel .zip scaricabile dal sito circuito.io nella pagina già linkata nel precedente post.

Cliccando qui si può scaricare lo zip.

Per quanto riguarda gli altri consigli, ne farò tesoro.

Questa è solo una prima stesura, poi riscriverò da capo tutto il codice, eliminando un sacco di immondizia e rinominando tutte le variabili.

EsafluoruroDiXeno:
La libreria HallU1881.h l'ho trovata nel .zip scaricabile dal sito circuito.io nella pagina già linkata nel precedente post.

Da quel che ho visto la libreria HallU1881.h è un mero richiamo delle funzioni della libreria Button.h, cioè è di fatto una libreria fittizzia e ridondante. Già un uso così inutile di librerie mi indurrebbe a non prendere in considerazione quell'esempio. Comunque a sperimentare non c'è niente di male, tieni però presente che perderai tempo in dei tentativi che sono diseducativi, secondo il mio personalissimo parere che può essere errato per altri.