ELS (Electronic Lead Screw) - 2.0

Moderatore: Junior Admin

Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

Vorrei rinnovare i ringraziamenti a McMax e ringraziare anche tutti coloro che hanno contribuito all'evoluzione di questo progetto, sbinf74 in particolare.

Ho fatto qualche prova e funziona tutto abbastanza bene salvo il fatto che la velocità di rotazione del mandrino che viene visualizzata è maggiore di circa un 20% rispetto a quella reale.
Ho cercato di capire come viene calcolata nello sketch ma sembra tutto corretto.
Al di là di questo problemino, ho sistemato il calcolo della velocità nella scheda "VelocitaMandrino" che risultava triplicata rispetto a quanto calcolato nei menu degli avanzamenti.
La riga errata è la seguente:

Codice: Seleziona tutto

if (digitalRead(ESC) == PRESSED || digitalRead(SEL) == PRESSED) stay = false; delay(300);
il ritardo di 300 millisecondi veniva eseguito sempre e questo comportava che in fase di calcolo i passi encoder rilevati erano riferiti a 300 millisec ma venivano utilizzati come se fossero stati eseguiti in 100.
Ho risolto sostituendo la riga precedente con le seguenti:

Codice: Seleziona tutto

if (digitalRead(ESC) == PRESSED || digitalRead(SEL) == PRESSED || digitalRead(SEL2) == PRESSED) 
    {
      stay = false;
      delay(300);
    }
E adesso qualche domanda.

1) Come si può fare per calcolare la velocità mandrino in modo che sia un po' più attendibile ?

2) Il valore massimo in cent/giro che si può assegnare per gli avanzamenti viene limitato in funzione dei seguenti valori: "NORTON_feed" (che non ho ben capito come venga assegnato) , "MaxStepperSpeed" (che ho impostato a 500) e "MandrelSpeed" (dovrebbe essere la velocità del mandrino). Il problema è che il valore massimo che riesco ad ottenere ad esempio a 600 giri/min del mandrino è di 31 cent/giro che è un po' bassino e comunque incoerente con quanto consentito quando si sceglie l'avanzamento in mm/min. Ho provato a leggere il codice ma non ne sono venuto a capo. Cosa posso fare ?

3) Come si determina il valore corretto da inserire nel parametro "MaxStepperSpeed" ?
Io ho inserito 500 g/min a capocchia, utilizzo un nema 24 da 5A alimentato a 36v e mi piacerebbe inserire il valore corretto. (sul datasheet non c'è scritto nulla a riguardo)

Grazie in anticipo a chi mi potrà rispondere..... tanto lo so che andando avanti sorgeranno altre domande. :???:
Avatar utente
McMax
CAPO OFFICINA
Messaggi: 9023
Iscritto il: dom gen 31, 2010 21:46
Località: Bussero (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da McMax »

Robyt scusa ma che versione del firmware stai usando ?
Per scrupolo ho controllato nella mia 1.6 ma non c'è traccia di quel delay nella condizione a cui ti riferisci. Ora so di aver riscritto quella funzione per cercare di migliorare la lettura della velocità e onestamente non ricordo come mai non avevo previsto il delay, probabilmente ho ragionato di metterlo da un'altra parte.
Quel delay comunque sia non ha nulla a che vedere con la misura della velocità o comunque con i tempi di controllo ad essa associati: serve solo come "debounce" per la pressione dei tasti "ESC" o "SEL".
Tra l'altro c'è una differenza sostanziale tra quella originale e come l'hai riscritta:
- nella originale l'unica istruzione che viene eseguita al verificarsi della condizione è "stay = false", il delay(300) non fa parte della condizione quindi viene eseguito a prescindere
- in quella che hai riscritto sia "stay = false" che "delay(300)" sono subordinati al verificarsi della condizione.

Comunque sia, in ogni caso, questa parte di codice che quoti non l'ho scritta io!

"1) Come si può fare per calcolare la velocità mandrino in modo che sia un po' più attendibile ?"
Il problema della precisione sulla lettura della velocità risiede nella funziona "millis()". Questa restituisce un clock in millisecondi assoluto che inizia a contare quando parte l'esecuzione del programma. Il problema è che questo Clock, per come è gestito, Non conta correttamente durante la gestione di un interrupt. Essendo che noi usiamo l'interrupt per leggere l'encoder, viene da se che il Clock di "millis()" risulta non preciso e quindi anche la lettura della velocità. Per risolvere dovrei rinunciare ad usare le funzioni di temporizzazione standard a favore di una gestione ad-hoc del timer e avere quindi un riferimento temporale più preciso.

"2) Il valore massimo in cent/giro che si può assegnare per gli avanzamenti viene limitato in funzione dei seguenti valori: "NORTON_feed" (che non ho ben capito come venga assegnato)...."
NORTON_feed è l'avanzamento in centesimi/giro della vite o della barra di alimentazione. Nel mio caso il tornio ha la barra quindi l'avanzamento che questa produce sul carro con un singolo giro è nell'ordine dei centesimi. Se per fare l'avanzamento usi la vite (se non hai la barra), devi cambiare nelle impostazioni il valore indicando sempre l'avanzamento in cent per un giro della vite. Se ad esempio la tua vite è passo 3mm, dovrai inserire 300 (300 cent/giro).
Hai a disposizione un totale di 8 valori diversi per NORTON_feed, 4 per il carro e 4 per il trasversale (per i torni che hanno barra e avanzamento sul trasversale). questi vengono caricati dalla EEPROM in due array: av_carro e av_trasv, ognuno da 4 celle intere. Puoi modificare le impostazioni di fabbrica della scheda EEPROM, nella lista dei #define hai gli 8 valori standard. Ricordati che se li modifichi da li devi lanciare il ripristino delle impostazioni per modificare i valori in EEPROM. Se hai solo la vite e non hai avanzamento sul trasversale puoi impostare per tutti i valori il passo in centesimi per un giro della vite (quindi, come da esempio di prima, con vite 3mm metti 300...)

"3) Come si determina il valore corretto da inserire nel parametro "MaxStepperSpeed" ?"
Devi guardare la curva di coppia del tuo motore stepper e capire qual'è la velocità massima a cui il motore ti da ancora una coppia accettabile. La coppia scende al salire della velocità pertanto va trovato il compromesso anche in funzione della coppia nominale del motore e della massa che deve muovere: muovere il carro di un graziano SAG sicuramente richiede molta più coppia che muovere il carro di un BV20......
A grandi linee comunque 500/600g/min per un motore stepper sono ok.
McMax

“None of us can change the things we’ve done. But we can all change what we do next.” – Fred Johnson

fulminato in tenera età
umbez
TORNITORE E FRESATORE
Messaggi: 1895
Iscritto il: lun set 29, 2008 23:19
Località: Cologno Monzese

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da umbez »

Max è il firm di sbinf, c'è sel2 che sarebbe il tasto del joystick. Io l'ho fatto così nella routine leggerei l'encoder a ogni giro completo prenderei il numero dei tick passati, sottrazione dei due tempi e calcolo rpm. Nel mio ho l'interrupt in quello di max si può inserire nella funzione di lettura.
Ù.
Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

Max hai ragione, il tuo sketch è diverso ma io , come intuito da umbez, ho usato quello di sbinf perchè utilizzo un display i2c.

@McMax
nel menu impostazioni ho assegnato i seguenti valori:
300 per i parametri "av_carro_1_default" e "av_trasv_1_default"
3.000 per il parametro "screw_pitch_default"
500 per il parametro "MaxStepperSpeed_default"

nella scheda "Avanzamento" le seguenti istruzioni determinano il valore massimo della velocità di avanzamento ("MaxFeed")

Codice: Seleziona tutto

if (mm_min) MaxFeed = (NORTON_feed * MaxStepperSpeed) / 100;     //calculate the max feed speed starting from the max stepper speed (mm/min)
      else MaxFeed = (unsigned int)((float)NORTON_feed * (float)MaxStepperSpeed) / MandrelSpeed;  //calculate the max feed based on mandrel speed and max stepper motore speede (cent/g)
      if (FeedSpeed > MaxFeed){ FeedSpeed = MaxFeed; lcd.setCursor(0, 2); lcd.print(FeedSpeed); lcd.print(" "); Update = true;} //if the current FeedSpeed is higher than the max, limit and print it
ipotizzando una velocità mandrino di 600 rpm e con i miei parametri dovrei ottenere:
MaxFeed = (300 * 500) / 600 = 250 cent/giro
ma il programma non mi consente di andare oltre i 31 cent/giro

appena riesco provo a intercettare i valori e stamparli sul monitor seriale
umbez
TORNITORE E FRESATORE
Messaggi: 1895
Iscritto il: lun set 29, 2008 23:19
Località: Cologno Monzese

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da umbez »

robyt se leggi la documentazione max lo spiega come settare il parametro norton
Ù.
Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

La documentazione l'ho letta più di una volta e in base alle caratteristiche del mio tornio che dispone solo della barra filettata con passo 3mm ho impostato questi valori:

Codice: Seleziona tutto

#define one_turn_mandrel_steps_default    1600  // 400x4
#define screw_pitch_default               3.000 // passo vite
#define one_turn_screw_steps_default      800   // microstepping a 400 e riduzione 1:2
#define AccelerationDelay_default         2000
#define DecelerationDelay_default         2000
#define CW_default                        LOW
#define CCW_default                       HIGH
#define av_carro_1_default                300  //avanzamento carro in centesimi/giro per rapporto semiNorton 1
#define av_trasv_1_default                300  //avanzamento trasversale in centesimi/giro per rapporto semiNorton 1
#define av_carro_2_default                300  //avanzamento carro in centesimi/giro per rapporto semiNorton 2
#define av_trasv_2_default                300  //avanzamento trasversale in centesimi/giro per rapporto semiNorton 2
#define av_carro_3_default                300  //avanzamento carro in centesimi/giro per rapporto semiNorton 3
#define av_trasv_3_default                300  //avanzamento trasversale in centesimi/giro per rapporto semiNorton 3
#define av_carro_4_default                300  //avanzamento carro in centesimi/giro per rapporto semiNorton 4
#define av_trasv_4_default                300  //avanzamento trasversale in centesimi/giro per rapporto semiNorton 4
#define offset_filetto_default            600 //offset per inizio filettatura (in passi stepper vite)
#define norton_default                    0   //posizione scatola NORTON avanzamenti (av_carro_1 e av_trasv_1) 
#define MaxStepperSpeed_default           500 //Max speed allowed to the stepper motor
ho sbagliato qualcosa ?
umbez
TORNITORE E FRESATORE
Messaggi: 1895
Iscritto il: lun set 29, 2008 23:19
Località: Cologno Monzese

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da umbez »

Hai configurato questo punto?
Avanzamento carro x: indica l’avanzamento, espresso in centesimi/giro, che una singola rotazione della barra di alimentazione esercita sul carro. Questa opzione presenta 4 diversi rapporti configurabili per quei torni dotati di barra avanzamenti e scatola norton meccanica che cambia il rapporto avanzamenti. Nel caso in cui non si disponga di barra gli avanzamenti andranno eseguiti con la vite pertanto qui sarà necessario indicare il passo della vite espresso in centesimi. In quest’ultimo caso basterà configurare un solo valore tralasciando gli altri 3
Ù.
Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

Infatti ho impostato a 300 il passo vite espresso in centesimi come si vede nel codice postato sopra
Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

Credo di aver risolto il problema della limitazione dei cent/giro.
La riga di codice nella scheda "Avanzamento" che calcola il limite in cent/giro è questa:

Codice: Seleziona tutto

else MaxFeed = (unsigned int)((float)NORTON_feed * (float)MaxStepperSpeed) / MandrelSpeed;  
Avendo messo nei miei parametri il valore 300 per "NORTON_feed " e 500 per "MaxStepperSpeed" il risultato della prima parte del calcolo è 150.000 che supera il valore consentito per un int senza segno (65.535). Di conseguenza il valore ottenuto era sballato.
Ho risolto aggiungendo semplicemente due parentesi:

Codice: Seleziona tutto

else MaxFeed = (unsigned int)(((float)NORTON_feed * (float)MaxStepperSpeed) / MandrelSpeed);  
Le righe interessate sono la 401 e la 603 dello sketch originale di McMax
matteou
FINALMENTE USO IL TORNIO
Messaggi: 564
Iscritto il: mar nov 10, 2009 12:36
Località: Udine

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da matteou »

A me sembra che le due espressioni siano uguali. Non dovrebbe cambiare nulla aggiungendo le due parentesi.
Non capisco l'utilita' del casting unsigned int (tanto MaxFeed e' gia un uint).
Il compilatore di arduino (ma penso che valga anche per c/c++ normale) esegue i calcoli usando lo spazio della variabile piu' grande, indipendentemente dalla grandezza della variabile che conterra' il risultato.
Esempio: float a=0; int b=500, int c=300; int d=200;
a= b*c/d; va in overflow, lo spazio per i calcoli sara' un int, quindi +/-32000 circa.
a= (float)b*c/d; non va in overflow perche' lo spazio per i calcoli sara' un float che riesce a contenere 500*300.

Avendo McMax fatto il casting delle variabili in float, la moltiplicazione NortonFeed*MaxStepperSpeed non va in overflow.
Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

Non conosco il C/C++ ne tantomeno le logiche del compilatore di arduino. Ho sempre lavorato con linguaggi di alto livello per la gestione e analisi di database e comunicazioni.
Pertanto il mio è un approccio di tipo euristico, cerco di capire in base alle mie conoscenze e faccio delle prove.
Nel caso specifico ho avviato il monitor seriale e intercettato i valori delle variabili che sono i seguenti:
"NORTON_feed " = 300
"MaxStepperSpeed" = 500
"MandrelSpeed" = 600
Nel calcolo originale ottengo un risultato errato per "MaxSpeed" = 109 mentre raggruppando il calcolo all'interno delle due parentesi aggiunte ottengo il risultato corretto = 250
Ciò è dovuto al fatto che la prima parte del calcolo (NORTON_feed * MaxStepperSpeed) da come risultato 150.000 che però viene plafonato a 65535 a causa di (unsigned int).
Infatti 65535/600 = 109 e spiccioli.
Se a qualcuno interessa ho realizzato un piccolo sketch che mi ha aiutato a capire.
Non hai i permessi necessari per visualizzare i file allegati in questo messaggio.
matteou
FINALMENTE USO IL TORNIO
Messaggi: 564
Iscritto il: mar nov 10, 2009 12:36
Località: Udine

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da matteou »

Fai benissimo a fare esperimenti ma un po' di teoria serve sempre per capire cosa si fa.
Due parole su cosa serve il cast esplicito. Quando vedi scritto float(NORTON_feed) oppure (float)NORTON_feed vuol dire che il compilatore "trasforma" la variabile NORTON_feed in un float. La trasformazione vale solo all'interno dell'operazione, NORTON_feed subito dopo torna a essere il tipo di variabile che era stata inizializzata.
Le due scritture sono equivalenti, la prima e' del c++, la seconda e' del c.

Quando si usa? Il primo esempio che mi viene in testa e' questo: hai due variabili int chiamate A=5 e B=6 e una variabile float chiamata C.
Se tu volessi fare C=A/B; C conterrebbe il risultato della divisione troncato dei decimali (quindi C=0).
Se ti interessa avere come risultato un numero con i decimali, devi fare il cast di una variabile, quindi puoi fare C=float(A)/B; in questo caso C=0.8333.

Nel caso specifico, fare il cast di due int in float e moltiplicarli non ha nessun senso (la moltiplicazione di due numeri interi dara' sempre un intero). Si perde solo tempo in calcoli inutili.
Probabilmente e' rimasto cosi' perche' McMax, nelle varie versioni, avra' cambiato qualcosa senza andare a modificare anche quelle operazioni.
Per bellezza di codice avresti potuto modificare in

Codice: Seleziona tutto

else MaxFeed = NORTON_feed * MaxStepperSpeed / MandrelSpeed; 
e avrebbe funzionato lo stesso (con risparmio di tempo e di leggibilita' del codice).

Infine, se una variabile va in overflow non si blocca al valore massimo ma riparte dal valore minimo.
Quindi se io avessi int A=65534 e facessi A=A+2; A non varrebbe 65535 ma varrebbe 1.
Avatar utente
robyt
APPRENDISTA E ADDETTO ALLE PULIZIE
Messaggi: 22
Iscritto il: mar gen 02, 2018 17:32
Località: Casorezzo (MI)

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da robyt »

Grazie per le delucidazioni matteu, qualcosa l'avevo intuita ma è sempre utile avere conferma da chi ne sa di più.
Per deformazione professionale, quando metto le mani su codice sviluppato da altri, cerco sempre di intervenire nel modo meno invasivo possibile.... ciò detto, ho modificato la riga come hai suggerito :smile:

L'unica cosa che mi ha lasciato qualche dubbio è il valore assunto da una variabile di tipo int in caso di overflow e quindi ho fatto qualche prova ed ho scoperto che:
- se le variabili in gioco sono tutte di tipo int il risultato è quello hai descritto tu
- se anche una sola delle variabili è di tipo float o double il risultato in caso di overflow è sempre 65535.
Riprendendo il tuo esempio: A=65534 e facessi A=(float)A+2; A = 65535
matteou
FINALMENTE USO IL TORNIO
Messaggi: 564
Iscritto il: mar nov 10, 2009 12:36
Località: Udine

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da matteou »

Errata corrige (dovuto al fatto che avevo scritto il post in 4 momenti diversi): 16bit-> 2^16-> 65536. Quindi i valori possibili spaziano da 0 a 65535.
Ovviamente A=65534; A=A+2;A varra' 0. Errore mio.

Per quanto riguarda il casting e' da fare un distinguo. Per gli interi il compilatore si fa furbo (anche senza ottimizzazione) e dice "aspetta va', se b e' un byte, perche' devo modificare b in un long se poi il risultato va a finire sempre in un byte? Quindi ignora il casting della variabile b.
Di seguito il codice assembly che permette di capire cosa fa il processore.

Codice: Seleziona tutto

uint8_t b=255;

    b=long(b)+1;
LDS	R24,$0100
SUBI	R24,$FF
STS	0100,R24
Il primo comando carica nel registro R24 il valore che c'e' in memoria all'indirizzo 0x0100 (255).
Poi, il che e' interessante, sottrae dal registro R24 il valore 0xFF (255). Quindi per aggiungere 1 toglie 255 dal valore iniziale.
Infine salva il risultato presente nel registro R24 nell'area di memoria all'indirizzo 0x0100.

Come vedi, il casting non e' stato preso in considerazione e ha lavorato come se il casting non ci fosse.

Nel caso di un casting float, il codice assembly si complica parecchio (non avendo un coprocessore matematico, il nostro povero uP deve emulare via sw i calcoli in virgola mobile).
In questo caso il compilatore fa il casting della variabile, usa 4 registri (32bit) fa tutti i conti in virgola mobile e, alla fine, salva in memoria solo i byte che servono (nel caso in cui la variabile dove salvi il risultato fosse un byte, salverebbe solo l'ultimo byte, se fosse un int salverebbe gli ultimi due byte, ecc...). Alla fine, per come e' fatto il sistema esadecimale, ti ritrovi sempre un overflow.
Puoi postare il codice dove ti risulta che si blocca al valore massimo?
sbinf74
TORNITORE E FRESATORE
Messaggi: 1349
Iscritto il: ven nov 21, 2008 14:34
Località: Roma

Re: ELS (Electronic Lead Screw) - 2.0

Messaggio da sbinf74 »

Scusate il ritardo nella risposta rispetto al codice di max ho aggiunto qualche delay qua e la per evitare il debounce dei tasti che rendevano alcune interfacce poco usabili.

Comunque non mi sono mai soffermato più di tanto sulla velocità mandrino perchè trovo scomodo sia all'interno di un menù dedicato, infatti in un'ultima revisione ho rimosso completamente questo menù.
Rispondi

Torna a “Elettronica ed elettrotecnica”