-

hey viewer, we're moving!

We are currently transitioning to a new web system, so we are not updating this wikisite anymore.

The public part of the new web system is available at http://www.ira.disco.unimib.it


Talk:INFIND2011/12 Motor control board

From Irawiki

Jump to: navigation, search

Parliamo qui di come vorremmo strutturare il codice in modo da fare qualcosa di sensato; poi scriveremo quanto deciso in modo definitivo nella pagina wiki

Contents

Data

Vi sono due modalità:

  • single data come abbiamo visto prima
  • è anche possibile richiedere uno o più dati in stream continuo: sulla seriale verranno quindi inviati alla frequenza fissata i dati richiesti.

STATUS

this variables does represent the state. Cannot be modified directly but can be read

  • POSE: posizione calcolata con i dati dell'encoder, cumulativa e normalizzata tramite step_to_angle
  • CURRENT: valore di corrente rilevato dal ponte h
  • POLOLU FAULT SIGNALS: valori di fault del ponte h
  • FSM STATE: stato della macchina a stati

Mapping dei dati

Abbiamo visto che i dati sono memorizzati in un array a cui il componente seriale può accedere per impostarli e leggerli. Per come vorremmo strutturare il codice però, i dati relativi a un modulo (adc, pwm ecc) dovrebbero stare nel modulo stesso. Pertanto bisogna organizzare un qualche mapping tra l'array del modulo seriale e le variabili dei singoli moduli. Questo mapping sarà particolarmente utile per i comandi che devono unicamente leggere questi valori in quanto possono essere eseguiti dal modulo seriale indipendentemente dallo stato. il mapping degli altri parametri sarà fatto dentro la macchina a stati e verranno settati tramite funzioni

Protocollo seriale

Definiamo i comandi che il pc deve poter dare con l'eventuale ritorno da parte del micro

Il micro manderà due tipi di messaggi: quelli in risposta a un comando, cioè che inviano i dati richiesti, e quelli dovuti a un evento. Di seguito quelli dovuti a un evento

Cosa descrizione
Fault ponte
Inizializzaizone assente
comando non valido il comando non esiste
parametri non validi
stato errato il comando mandato non può essere eseguito in questo stato
ack ack di ricezione ed esecuzione del comando

DOMANDE

ADC - media dei valori [ANSWERED]

abbiamo detto che ci piacerebbe avere una media di n valori presi dall'adc. quanto è sensato sia grande questo n? si tenga presente che i valori vengono salvati dall'adc pertanto non abbiamo occupazione di tempo cpu dipendente da n. l'unica cosa è il costo di calcolare la media che viene fatto alla frequenza con cui si vuole il dato.

ho due proposte per questo problema

  1. n è fisso hardcoded a un numero da valutarsi
  2. n può essere scelto dall'utente via seriale

Visto che il tempo di campionamento può essere scelto via seriale la soluzione 2 mi sembrerebbe più sensata ma questo implica di effettuare una allocazione dinamica. Oltre al macello di deallocare al momento giusto, il punto è che usare una malloc non è così facile. bisogna aggiungere delle funzioni che mancano e non so bene come implementarle.

A questo proposito potremmo pensare di allocare comunque uno spazio massimo (ad es 64 short) ed eventualmente usarne di meno impostando adeguatamente il dma.

detto questo rimarrebbe facile la soluzione numero 1 ma a questo punto rimane da capire a quanto settare n: la frequenza di clock dell'adc massima è 12Mhz ottenuta con clock APB2/6 (al massimo potrebbe essere 14 ma dovremmo avere un prescaler da 5.1); il sample time in clock può essere settato da 14 a 252, quindi acquisire un campione impiega da 1.16 a 21 us; secondo sorrenti vorremmo andare a circa 100 volte la frequenza del controllo in corrente; se quest'ultimo fosse a 1kHz vuol dire avere un dato dal sensore a 100kHz quindi un dato ogni 10us, il che vuol dire poter far la media tra 8 e 0.5 valori nel caso pessimo -.- . Ovviamente si potrebbe far la media ugualmente tra un numero arbitrario di valori ma questo introdurrebbe un ritardo nell'azione di controllo, ad esempio se andando alla velocità massima mediassi 16 valori avrei la media tra le ultime 8 letture appena acquisite dal sensore e le 8 acquisite al giro precedente..

ovviamente dobbiamo tener conto che non stiamo facendo solo quello ma che abbiamo anche altre cose da fare nel mezzo.

altra questione: la media attualmente viene fatta sui valori messi nell'array apposito dal dma. mentre faccio la media devo interrompere il dma?

come facciamo?

usiamo la soluzione proposta allocando uno spazio fisso di 64. la media viene fatta su un sottoinsieme di questi valori. la velocità sarà un problema dell'utente

ADC - watchdog interrupt

come ci comportiamo in caso di interrupt dal watchdog sul sensore di corrente? questo interrupt scatta se il valore è sopra o sotto una certa soglia settata via seriale. alcune posibilità sono:

  • segnalare la cosa al controllo
  • segnalare la cosa al controllore del ponte
  • segnalare via seriale

un altro problema sul watchdog è che se siamo in modalità continua e il valore è sopra la soglia l'interrupt viene generato ad ogni conversione, con il risultato di essere sempre nella routine di gestione dell'interrupt. come ci si comporta in questo caso? dopo il primo interrupt lo disabilito per un tot?

Come inserire un nuovo comando all'interno della gestione della seriale

  • Per prima cosa, in /serial.h/, aggiungere un nuovo define come quelli presenti e abbinare il carattere che si vuole utilizzare.
  • Inserire in modo corretto all'interno della funzione isoneshotcmd il caso relativo al comando appena creato.
  • Se il comando richiede all'utente di fornire una posizione o una maschera ma NON richiede all'utente di inserire alcun valore (e.g. si tratta di un comando di output che richiede solamente la posizione della variabile da leggere) inserire all'interno della funzione isoutputcmd un nuovo "case" in modo che venga resitituito true.

    Se il comando invece richiede maschera + valori o posizione + valori (oppure se il comando è oneshot!) non inserire niente.

  • In DMA1_Channel5_IRQHandler:
    • Nello stato CMD:
      • Nel caso in cui si stia inserendo un nuovo comando one-shot farlo all'interno del ramo "else" dell'IF presente. L'azzeramento di scmd, lo switch allo stato corretto e il set del numero corretto di caratteri dovrebbe essere già presente.
      • Nel caso in cui si stia inserendo un nuovo comando NON one-shot farlo all'interno del ramo "if". Impostare il prossimo stato corretto (devo leggere una maschera? una posizione? oppure direttamente dei valori?) e scegliere il numero di caratteri da leggere.
    • Nello stato MASK:
      • Non si dovrebbe fare niente, la lettura della maschera dovrebbe essere "standard".
    • Nello stato Position:
      • Come nello stato MASK.
    • Nello stato VALUES:
      • Come sopra, se si vuole modificare come i valori vengono letti è necessario farlo all'interno di process_param.

Come inserire nuove variabili all'interno della gestione della seriale

  • Per prima cosa, in /serial.h/, aggiungere un nuovo define per la maschera (in coda a quelli già presenti).
 RICORDARSI, DA ORA IN POI, DI MANTENERE L'ORDINE CON LE ALTRE
 MASCHERE, LA LETTURA TRAMITE SERIALE ALTRIMENTI POTREBBE ESSERE ERRATA.
  • In calc_p_length inserire un nuovo if che faccia l'AND tra la maschera passata alla funzione e quella appena definita nell'header. Aumentare il valore di length in modo corretto (il numero di byte equivalenti alla lunghezza della variabile, e.g. un float sono 4 byte).
  • In process_read_param inserire un if tra la maschera passata alla funzione e la propria (quella definita in serial.h). Leggere i valori partendo da rparameter[index], se necessario modificare il valore letto come preferite ed inserirlo nella variabile che volete settare.

    Ricrodarsi di aumentare il valore di index del numero di caratteri letti in modo che la lettura successiva non legga gli stessi valori sulla stringa.

  • In write_param_according_to_mask creare un if tra la maschera passata alla funzione e la propria. Appendere in coda a wparameter (a partire dalla posizione length) il numero corretto di byte ed incrementare length.

    Per le variabili float ho scritto appendf_param che dovrebbe fare questa procedura automaticamente (questa funzione ritorna 4, la lunghezza in byte di un float).

    Io tolgo anche l'1 nella maschera, in realtà non sarebbe nessario.

Se ci sono problemi contattatemi!

Personal tools