info arduino Due

ciao a tutti ragazzi, avrei bisogno di un po di info riguardo arduino Due, in particolare sto cercando riguardo la possibilità di cambiare le soglie dei timer interni al processore per variare la frequenza della funzione analogWrite (in pratica sarebbe la funzione fastPWM dell' arduino uno)...
tutto questo poiche ho bisogno di controllare il pwm con un periodo non inferiore ai 2000uS (standard la scheda è settata a 1000uS ossia 1kHz)..ho spulciato sul datasheet del processore ma non sono riuscito a trovare esattamente quello che mi serve..
quel tempo è riferito, come magari si capisce già, al pilotaggio di un brushless tramite un esc..
qualcuno gentilmente mi sa aiutare in merito?
grazie

Basta prendere il datasheet dell'Atmega328 del SAM3X e lì trovi tutti i registri per configurare i timer secondo le tue esigenze.
Tieni solo conto che se alteri il timer 0 poi tutte le funzioni temporali di Arduino risulteranno sballate.

Leo, lui parla del SAM3X. :sweat_smile:

PaoloP:
Leo, lui parla del SAM3X. :sweat_smile:

Corretto.
Il ragionamento comunque non cambia. Basta programmare accuratamente i registri del timer da modificare secondo quanto riportato sul datasheet e si può manipolare a piacimento il comportamento del segnale PWM generato sui pin corrispondenti. :wink:

ma infatti cm gia detto ho sfogliato il datasheet, ho trovato la parte relativa ai timer e i registri interessati ma continuo a riscontrare errori di variabili non dichiarate nella compilazione del codice..

i registri dovrebbero essere questi se non sbaglio, ma non saprei come manipolarli:
Sezione 37 del datasheet
http://www.atmel.com/Images/doc11057.pdf

gptxever:
ma infatti cm gia detto ho sfogliato il datasheet, ho trovato la parte relativa ai timer e i registri interessati ma continuo a riscontrare errori di variabili non dichiarate nella compilazione del codice..

Pubblica il codice e specifica quali costanti non sarebbero dichiarate.

i registri dovrebbero essere questi se non sbaglio, ma non saprei come manipolarli:
Sezione 37 del datasheet
http://www.atmel.com/Images/doc11057.pdf

Devi prima calcolarti la frequenza che vuoi ottenere. A questo punto scegli la modalità PWM (Fast PWM o Phase Correct PWM). Quindi importi i registri per attivare l'output su uno dei pin gestiti dal timer.

il procedimento da fare piu o meno l'ho capito, ma non avendoli mai utilizzati o modificati i registri del sistema mi trovo in difficolta soprattutto sulla sintassi.........non conosco i nomi dei registri e quali sono i singoli bit da modificare per ottenere la frequenza desiderata........

navigando un po nel web sono venuto a conoscenza di alcune funzioni gia compilate rese disponibili penso dalla casa costruttrice che permettono di modificare piu semplicemente i paramentri del pwm senza andare ad agire nei registri. sono le funzioni PWMC_xxxxxxxxxx()

extern void PWMC_ConfigureChannel(
Pwm* pPwm,
uint8_t channel,
uint32_t prescaler,
uint32_t alignment,
uint32_t polarity);
extern void PWMC_ConfigureChannelExt(
Pwm* pPwm,
uint8_t channel,
uint32_t prescaler,
uint32_t alignment,
uint32_t polarity,
uint32_t countEventSelect,
uint32_t DTEnable,
uint32_t DTHInverte,
uint32_t DTLInverte);
extern void PWMC_ConfigureClocks(uint32_t clka, uint32_t clkb, uint32_t mck);
extern void PWMC_SetPeriod( Pwm* pPwm, uint8_t channel, uint16_t period);
extern void PWMC_SetDutyCycle( Pwm* pPwm, uint8_t channel, uint16_t duty);
extern void PWMC_SetDeadTime( Pwm* pPwm, uint8_t channel, uint16_t timeH, uint16_t timeL);
extern void PWMC_ConfigureSyncChannel( Pwm* pPwm,
uint32_t channels,
uint32_t updateMode,
uint32_t requestMode,
uint32_t requestComparisonSelect);
extern void PWMC_SetSyncChannelUpdatePeriod( Pwm* pPwm, uint8_t period);
extern void PWMC_SetSyncChannelUpdateUnlock( Pwm* pPwm );
extern void PWMC_EnableChannel( Pwm* pPwm, uint8_t channel);
extern void PWMC_DisableChannel( Pwm* pPwm, uint8_t channel);
extern void PWMC_EnableChannelIt( Pwm* pPwm, uint8_t channel);
extern void PWMC_DisableChannelIt( Pwm* pPwm, uint8_t channel);
extern void PWMC_EnableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2);
extern void PWMC_DisableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2);
extern uint8_t PWMC_WriteBuffer(Pwm pwmc,
void buffer,
uint32_t length);
extern void PWMC_SetOverrideValue( Pwm
pPwm, uint32_t value);
extern void PWMC_EnableOverrideOutput( Pwm
pPwm, uint32_t value, uint32_t sync);
extern void PWMC_DisableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync);
extern void PWMC_SetFaultMode( Pwm* pPwm, uint32_t mode);
extern void PWMC_FaultClear( Pwm* pPwm, uint32_t fault);
extern void PWMC_SetFaultProtectionValue( Pwm* pPwm, uint32_t value);
extern void PWMC_EnableFaultProtection( Pwm* pPwm, uint32_t dwChannel, uint32_t dwValue ) ;
extern void PWMC_ConfigureComparisonUnit( Pwm* pPwm, uint32_t x, uint32_t value, uint32_t mode);
extern void PWMC_ConfigureEventLineMode( Pwm* pPwm, uint32_t x, uint32_t mode);

anche qui cmq trovo difficolta sempre nella sintassi, ossia ad esempio per la funzione:
PWMC_SetPeriod( Pwm* pPwm, uint8_t channel, uint16_t period); devo inserire ad esempio:
PWMC_SetPeriod(PWM_INTERFACE,PWM_CH2, 2000);

ma a questo punto, a parte che non vedo cambiamenti sul canale 2, prima di effetuare questa funzione, va configurato e settato ad esempio il canale o abilitato?il numero del canale poi corrisponde al pin di output sulla scheda arduino?

La "casa costruttrice" di Arduino è il team Arduino stesso e tutto quello che offre è compreso nell'IDE :wink:
Forse questa è una libreria esterna, scritta cioè da un comune utente della scheda.

Comunque se la libreria modifica il timer, poi usando l'analogWrite sul pin collegato dovresti trovare un segnale di frequenza differente rispetto agli altri pin PWM collegati ai timer non modificati.

casa costruttrice intendo del microprocessore, la atmel, infatti quelle funzioni le ho trovate su piu di una pagina dove specifica le caratteristiche del micro.......
utilizzando solo la funzione PWMC_setperiod non ho trovato nessuna variazione nella frequenza sui pin di uscita...probabilmente, quello che intendo io è che andrà magari abilitato o configurato prima di poter settare il periodo...magari invece mi sbaglio.....

uno stratagemma che ho trovato e sto usando temporaneamente è quello di cambiarlo nell IDE di arduino, esattamente nella libreria variant.h.....
da li ho semplicemente scambiato i 1000Hz di default con quelli che interessano a me...ma cm ho gia detto vorrei utilizzare questo metodo solo temporaneamente e trovare qualcosa di piu "corretto" via software...

Non devi andare a toccare il core. Devi semplicemente impostare i registri per ottenere ciò che vuoi nel tuo sketch.
Il core di Arduino preimposta i timer per funzionare in una certa maniera (Fast PWM o Phase Correct PWM, a seconda dei timer), ma tu puoi nel tuo sketch cambiare questi setup.

Nella funzione analogWrite trovo questa funzione:

PWMC_ConfigureClocks(PWM_FREQUENCY * PWM_MAX_DUTY_CYCLE, 0, VARIANT_MCK);

Prova nel tuo sketch a cambiare PWM_FREQUENCY con quello che vuoi e poi il duty cycle seguente.

ok...visto che la strada allora è quella proverò a fare un po di test con le funzioni che ho scritto sopra e mi hai suggerito tu...oscilloscopio sotto mano e un po di pazienza:)...grazie intanto leo..ti faro sapere..

gptxever:
ok...visto che la strada allora è quella proverò a fare un po di test con le funzioni che ho scritto sopra e mi hai suggerito tu...oscilloscopio sotto mano e un po di pazienza:)...grazie intanto leo..ti faro sapere..

OK.
Io dico che con questa funzione qualcosa di buono ci combini :wink:

leo buone notizie:).... ho fatto qualche test e sono arrivato a queste conclusioni:

ho ottenuto la frequenza desiderata in questo modo:

void setup(){
....
....
  analogWrite(Outmot1, 0);
  analogWrite(Outmot2, 0);
  analogWrite(Outmot3, 0);
  analogWrite(Outmot4, 0);
  
  PWMC_ConfigureClocks(500 * PWM_MAX_DUTY_CYCLE , 0, VARIANT_MCK);
....
....

scopro che:
i canali di cui viene modificata la frequenza del PWM sono solo: 6,7,8,9.
nel void setup() necessita l'istruzione

analogWrite(pin_uscita, valore PWM);

e rispettivamente prima di

PWMC_ConfigureClocks(500 * PWM_MAX_DUTY_CYCLE , 0, VARIANT_MCK);

ma non saprei dire il motivo (forse xke riconosce l'out come abilitato o inizializzato, o una roba del genere penso)..

in seguito per modificare il duty cycle posso utilizzare sia il classico "analogRead()" o la funzione " PWMC_SetDutyCycle(PWM_INTERFACE, PWM_CHx, value);"...non ho notato differenze...

gptxever:
leo buone notizie:).... ho fatto qualche test e sono arrivato a queste conclusioni:

Ottimo :wink:

scopro che:
i canali di cui viene modificata la frequenza del PWM sono solo: 6,7,8,9.

Il SAM3X è un chip molto complesso. Bisognerebbe guardarsi tutto il core e capire cos'è supportato e cosa no. Non hai idea delle periferiche che integra, e se parliamo solo di timer ce ne sono almeno 4 o 5 differenti (RTC, SysTick, Watchdog, Pwm, RTT).

nel void setup() necessita l'istruzione

analogWrite(pin_uscita, valore PWM);

e rispettivamente prima di

PWMC_ConfigureClocks(500 * PWM_MAX_DUTY_CYCLE , 0, VARIANT_MCK);

ma non saprei dire il motivo (forse xke riconosce l'out come abilitato o inizializzato, o una roba del genere penso)..

Forse perché nel core c'è qualche altra inizializzazione che non ho visto e che l'analogWrite richiama.