Con riferimento al precedente post ( ritardo tra 1 e due microsec) mi trovo a dover fare una serie di if che vado a descrivere :
int F ; //
se F Va da 0 a 125 chiama delay100();
se F Va da 126 a 225 chiama delay200();
se F Va da 226 a 325 chiama delay300();
se F Va da 326 a 425 chiama delay400();
ecc ecc omissis....
se F Va da 9500 a 10500 chiama delay10000();
c'è un modo più veloce che non fare tanti if a cascata?
vediamo se riesco a spiegarmi
perché poi sarò occupato probabilmente, quindi vediamo di farlo adesso
ammesso così:
0-125 ->100
126-225 ->200
226-325 ->300
e via così..
Lo OP i fare:
int calcolaattesa(int F){
if (F > 9500) return 10000;
if (F > ....
...
if (F > 325) return 400;
if (F > 225) return 300;
if (F > 125) return 200;
return 100;
}
come vedi è più snello e corto e semplice da leggere che una catena di if..elseif con doppia condizione: > && <
oppure puoi costruire un array di soglie e valori
int soglie[]={9500,...,325,225,125,0};
int valori[]={10000,...,400,300,200,100};
// con la sua dimensione
#define dimensione sizeof soglie / sizeof sogle[0]
//per poi ciclarlo
for(int i=0; i< dimensione, i++){
if (F >= soglie[i]) return valori[i];
}
// che con poche righe te la cavi, comodo per tante differenti soglie
oppure, da ultimo, posto che tutti gli if siano come i primi 4
puoi usare una relazione matematica semplice
delay(int( (F-25) ) / 100 * 100 + 100);
dove ho usato un casting esplicito perchè non so di che tipo sia F
a proposito, solitamente le maiscole sono usate per le costanti
@nid69ita , @Standardoil : forse ad entrambi è sfuggito il riferimento al thread precedente, l'OP non vuole richiamare la funzione delay() con un parametro variabile, ma le varie funzioni delay100(), delay(200) etc che ha creato con asm(nop).
L'esempio 1 va bene lo stesso
Invece di un return si mette chiamata alla funzione e return
L'esempio 2 ancora meglio
Array di puntatore a funzione void con argomento void
Si chiama la funzione puntata dell'elemento trovato
L'esempio 3 è forse quello che richiede maggiori modifiche
Serve di usare il 'risultato del calcolo' come indice dell'array di puntatore a funzione, creato apposta
Grazie a tutti,
ho fatto un pezzo di lavoro con un loop di prova che mi chiama le rampe più veloci.
Poi per le rampe più lente ho fatto un paio di funzioni con parametro, e va abbastanza bene.
Ora però sono nei guai, perchè , avendo usato i puntatori a funzioni (non è farina del mio sacco) per chiamare ripetutamente le rampe, non so come aggiungere il parametro a queste funzioni.
In pratica devo puntare
FunctionPointed = Rampa10_1000ms(200); ....dove 200 è il parametro, ma nonlo so proprio fare.
Grazie
Risolto, do priorità a quelle più veloci, e per quelle lente c'è tutto il tempo di fare calcoli ulteriori.
La funzione principale è ArrotondaTempoRampa(); che sistema il puntatore alla funzione che verrà chiamata velocemente fino ad un aggiornamento (ancora da implementare.
Grazie a tutti.
/*
* Arduino NANO + DAC AD1280 connesso in parallelo sul portD generano una rampa raziometrica
* Il parametro "unsigned long TempoRampa" decide quanto dura la rampa, da 100usec a 3 sec
* - 100 = 100usec
* - 1.000 = 1msec
* - 1.000.000 = 1 sec
* - 3.000.000 = 3 sec
* - se vale 0 il DAC va subito a fondo scala
* - per altri valori il TempoRampa è espresso in microsecondi
* ----------------------------------------------------------
*
*/
unsigned long TempoRampa = 0;
//prototipi
void ArrotondaTempoRampa(void);
void RampaLenta(void); //rampa se t > 9 msec
void DacFullScale(void); // dac a fondo scala
void DacZero(void); //azzera la tensione
void Rampa75usec(void);
void Rampa100usec(void);
void Rampa150usec(void);
void Rampa200usec(void);
void Rampa250usec(void);
void Rampa300usec(void);
void Rampa400usec(void);
void Rampa500usec(void);
void Rampa600usec(void);
void Rampa700usec(void);
void Rampa800usec(void);
void Rampa900usec(void);
void Rampa1msec(void);
void Rampa2msec(void);
void Rampa3msec(void);
void Rampa4msec(void);
void Rampa5msec(void);
void Rampa8msec(void);
void Rampa10_1000ms(int RampaMilliS);
void Rampa1000_10000ms(int RampaMilliS);
int cicli;
typedef void (*GeneralFunction) (void); //puntatore alla funzione
GeneralFunction FunctionPointed = NULL;
//-------------------------------
void setup() {
//Serial.begin(38400);
//Serial.begin(115200);
//while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
//}
FunctionPointed = Rampa75usec;
DDRD=B11111111;
}
//-------------------------------
//-------------------------------
void loop(){
// testa rampa > 10 msec fino a 2sec
TempoRampa = 2000000;
// valori testati
// TempoRampa = 20000;
// TempoRampa = 50000;
// TempoRampa = 90000;
// TempoRampa = 150000;
// TempoRampa = 250000;
// TempoRampa = 500000;
// TempoRampa = 1000000;
// TempoRampa = 2000000;
ArrotondaTempoRampa();
for (cicli = 1; cicli<100; cicli++){
(FunctionPointed)();
delay(TempoRampa/1000);
}
}
//-------------------------------
void loop5(){
// testa rampe con chiamata da Arrotondamento da 1usec a 9999usec
for (unsigned long Testusec = 1000; Testusec<10000; Testusec++){
TempoRampa = Testusec;
ArrotondaTempoRampa();
for (cicli = 1; cicli<100; cicli++){
(FunctionPointed)();
delay(1);
}
delay(10);
Testusec = Testusec + 499; // lo facciamo a step di 500, altrimenti è eterno
}
}
//-------------------------------
void loop4(){
// testa rampe con chiamata da Arrotondamento da 1usec a 9999usec
for (unsigned long Testusec = 500; Testusec<1001; Testusec++){
TempoRampa = Testusec;
ArrotondaTempoRampa();
for (cicli = 1; cicli<10; cicli++){
(FunctionPointed)();
delay(1);
}
delay(10);
}
}
//-------------------------------
void loop3(){
// testa rampe con chiamata da Arrotondamento da 1usec a 9999usec
for (unsigned long Testusec = 1; Testusec<501; Testusec++){
TempoRampa = Testusec;
ArrotondaTempoRampa();
for (cicli = 1; cicli<10; cicli++){
(FunctionPointed)();
delay(1);
}
delay(10);
}
}
//-------------------------------
//-------------------------------
void loop2() {
//testa le rampe da 100usec a 1msec
FunctionPointed = Rampa100usec;
for (cicli = 1; cicli<10000; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa150usec;
for (cicli = 1; cicli<7500; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa200usec;
for (cicli = 1; cicli<5000; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa250usec;
for (cicli = 1; cicli<4000; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa300usec;
for (cicli = 1; cicli<3300; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa400usec;
for (cicli = 1; cicli<2500; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa500usec;
for (cicli = 1; cicli<2000; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa600usec;
for (cicli = 1; cicli<1600; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa700usec;
for (cicli = 1; cicli<1400; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa800usec;
for (cicli = 1; cicli<1200; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa900usec;
for (cicli = 1; cicli<1100; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa1msec;
for (cicli = 1; cicli<1000; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa2msec;
for (cicli = 1; cicli<500; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa3msec;
for (cicli = 1; cicli<333; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa4msec;
for (cicli = 1; cicli<250; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa5msec;
for (cicli = 1; cicli<200; cicli++){
(FunctionPointed)();
}
FunctionPointed = Rampa8msec;
for (cicli = 1; cicli<125; cicli++){
(FunctionPointed)();
}
}
//***********************************************
//***********************************************
//***********************************************
/*
- input Durata in microsecondi (TempoRampa)
- output punta la funzione giusta
void Rampa75usec(void);
void Rampa100usec(void);
void Rampa150usec(void);
void Rampa200usec(void);
void Rampa250usec(void);
void Rampa300usec(void);
void Rampa400usec(void);
void Rampa500usec(void);
void Rampa600usec(void);
void Rampa700usec(void);
void Rampa800usec(void);
void Rampa900usec(void);
void Rampa1msec(void);
void Rampa2msec(void);
void Rampa3msec(void);
void Rampa4msec(void);
void Rampa5msec(void);
void Rampa8msec(void);
void Rampa10_1000ms(int RampaMilliS);
void Rampa1000_10000ms(int RampaMilliS);
La soglia è l'intero tra i due valori limitrofi (ad esempio tra 75 e 100 la soglia è 88)
*/
void ArrotondaTempoRampa(void){
if (TempoRampa == 0) { FunctionPointed = DacFullScale; return 0; }
if (TempoRampa < 88) { FunctionPointed = Rampa75usec ; return 0; }
if (TempoRampa < 125) { FunctionPointed = Rampa100usec; return 0; }
if (TempoRampa < 175) { FunctionPointed = Rampa150usec; return 0; }
if (TempoRampa < 225) { FunctionPointed = Rampa200usec; return 0; }
if (TempoRampa < 275) { FunctionPointed = Rampa250usec; return 0; }
if (TempoRampa < 350) { FunctionPointed = Rampa300usec; return 0; }
if (TempoRampa < 450) { FunctionPointed = Rampa400usec; return 0; }
if (TempoRampa < 550) { FunctionPointed = Rampa500usec; return 0; }
if (TempoRampa < 650) { FunctionPointed = Rampa600usec; return 0; }
if (TempoRampa < 750) { FunctionPointed = Rampa700usec; return 0; }
if (TempoRampa < 850) { FunctionPointed = Rampa800usec; return 0; }
if (TempoRampa < 950) { FunctionPointed = Rampa900usec; return 0; }
if (TempoRampa < 1500) { FunctionPointed = Rampa1msec ; return 0; }
if (TempoRampa < 2500) { FunctionPointed = Rampa2msec ; return 0; }
if (TempoRampa < 3500) { FunctionPointed = Rampa3msec ; return 0; }
if (TempoRampa < 4500) { FunctionPointed = Rampa4msec ; return 0; }
if (TempoRampa < 6500) { FunctionPointed = Rampa5msec ; return 0; }
if (TempoRampa < 9000) { FunctionPointed = Rampa8msec ; return 0; }
if (TempoRampa > 9000) { FunctionPointed = RampaLenta; return 0; }
}
//***********************************************
// per rampa di durata da 10msec a 1000msec si usa Rampa10_1000ms(int RampaMilliS);
// per rampa di durata da 1sec a 10 sec si usa Rampa1000_10000ms(int RampaMilliS);
void RampaLenta(void){
if (TempoRampa < 1000000){
Rampa10_1000ms(TempoRampa / 1000); // vuole il parametro in millisecondi
} else {
Rampa1000_10000ms(TempoRampa / 1000);
}
}
//***********************************************
void DacFullScale(void){
PORTD=0;
}
void DacZero(void){
PORTD=255;
}
//***********************************************
void Rampa75usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
}
}
void Rampa100usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
asm("nop");
asm("nop");
}
}
void Rampa150usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
void Rampa200usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
void Rampa250usec(void){
/*
for(int y=255;y>-1;y--){
PORTD=y;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
*/
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(2);
}
}
void Rampa300usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
//-------------------------------------------------
void Rampa400usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(2);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
void Rampa500usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(3);
}
}
void Rampa600usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(3);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
void Rampa700usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(3);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
void Rampa800usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(4);
asm("nop");
}
}
void Rampa900usec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(4);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
//-------------------------------------------------
void Rampa1msec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(5);
}
}
void Rampa2msec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(9);
}
}
void Rampa3msec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(13);
}
}
void Rampa4msec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(17);
}
}
void Rampa5msec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(21);
}
}
void Rampa8msec(void){
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(34);
}
}
//-------------------------------------------------
// rampa con durata da 10ms a 1000 msec
//bisogna dividere il parametro per circa 1,3
void Rampa10_1000ms(int RampaMilliS){
float float2;
int int2;
float2 = RampaMilliS * 10;
float2 = float2 / 13;
int2 = float2;
int2 = int2 * 5;
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(int2);
}
}
//-----------------------------------
void xxRampa1000_10000ms(int RampaMilliS){
for(int y=255;y>-1;y--){
PORTD=y;
delay(RampaMilliS * 4);
}
}
void Rampa1000_10000ms(int RampaMilliS){
int int3;
int3 = RampaMilliS * 4;
for(int y=255;y>-1;y--){
PORTD=y;
delayMicroseconds(int3);
}
}
Non è la risposta al topic.
Il core Arduino mantiene abilitati gli interrupt globali, per cui durante un ciclo for o altro tra una istruzione assembly e l'altra può essere sollevato una IRQ e servita la relativa ISR. Questo accade per il contatore restituito da millis(), dove una ISR viene chiamata ogni 1ms. Il for che realizza la rampa non è sincronizzato (mi pare) per cui può verificarsi la chiamata alla ISR per incrementare il contatore di millis. Per aggirare il problema si può rendere atomica una porzione di codice che per natura non lo è, lo puoi fare come ho mostrato.