Modificare il valore attuale, in base al precedente

Ciao.

Dopo la positiva esperienza avuta confrontandomi col forum, sono di nuovo a chiedere il vostro gentile aiuto.

Il mio obiettivo è trattenere una "copia" del valore precedente (al tempo t=0) per aumentarlo, o diminuirlo, a seconda di un iinput fornito dall'utente tramite potenziomentro.

Cioè, nello stream di dati che vedo scorrere a cascta su temrinale, ho un valore fisso (diciamo "Setpoint"), ed un valore che si muove entro un certo intervallo, dipendentemente da quanto muovo il potenziometro (diciamo: "ch3").

Io vorrei: Setpoint[fadesso]=Setpoint[prima]+variazione_ch3.

Insomma il valore di Setpoint attuale è una combinazione lineare del suo valore precedente e dell'imput dell'utente.

Come posso fare? Non riesco a tradurre la mia idea in linguaggio arduino.

Grazie a chiunnque voglia aiutarmi. un saluto Marco

Hai già scritto qualcosa? Giusto per vedere come è possibile aiutarti ? Leggi già il valore del potenziometro ?

ciao. Grazie per la risposta.

Sì, ho già tutto pronto. I potenziomentro è lo stick di un telecomando che, via ponte radio, comunica con arduino. Muovendo in avanti/indietro lo stick della manetta, vorrei aumentare/diminuire il valore Setpoint misurato da un barometro. Tale valore di pressione viene convertito in quota (quota barometrica).

Faccio tutto questo per controllare la quota bersaglio (Setpoint) "inseguendo" un valore di pressione che io imposto via telecomando. Il fatto di aumentare/diminuire il Setpoint (in questo caso la quota), si tramuta in un segnale che viene inviato ai motori che aumentano o riducono la loro rotazione. Ciò implica che il velivolo si aumenti o diminuisca la quota in funzione della quota imposta e di quella a cui effettivamente si trova (misurata).

H(p) modalità Setpoint Output PID INgresso manetta Stick manetta 175.856 (Alt. Hold) Setpoint:175.37 Output:0.00 Throttle Input:1360.00 yy:0.000 Kp:10.00 Ki:1.00 Kd:0.00 175.856 (Alt. Hold) Setpoint:175.37 Output:0.00 Throttle Input:1360.00 yy:-0.600 Kp:10.00 Ki:1.00 Kd:0.00 175.822 (Alt. Hold) Setpoint:175.37 Output:0.00 Throttle Input:1360.00 yy:-0.600 Kp:10.00 Ki:1.00 Kd:0.00 175.789 (Alt. Hold) Setpoint:175.37 Output:0.00 Throttle Input:1360.00 yy:-0.600 Kp:10.00 Ki:1.00 Kd:0.00

Ignora le ultime tre colonne (Kp, Ki, Kd).

-La prima colonna è la quota barimetrica MISURATA ( H(p) ). -La terza è la quota barimetrica che voglio inseguire -rimane sempre costante ed è quella misurata al momento del passaggio tra modalità manuale e modalità "Altitude hold": -La sesta colonna è la posizione dello stick (rimappata). C'è una zona centrale in cui segna sempre zero. Appena esco da quella zona centrale, mi da valori negativi (se lo stick è tirato indietro) o positivi (se spingo lo stick in avanti).

Le tre colonne descritte soopra sono legate tra loro ed l'algoritmo che le collega è di tipo retroattivo ad anello chiuso (PID).

Dunque, il mio obiettivo è che il valore della terza colonna (Setpoint), che ora è sempre fisso, possa invece essere influenzato dal valore letto nella sesta colonna, che rispecchia il valore del segnale sul telecomando.

Cioè in soldoni, gli dico a quale quota stazionare.

Molte Grazie per l'aiuto. Marco

per come l'hai descritta e io l'ho capita è proprio come avevi scritto nel primo post:

Setpoint=Setpoint+variazione_ch3

che può essere scritta anche come:

Setpoint+=variazione_ch3

messo subito dopo il codice che legge il valore della manetta, ovviamente non conoscendo il codice dello sketch e il nome delle variabili, ho presupposto che i nomi che hai utilizzato tu fossero proprio quello delle variabili che usi nel tuo programma...

La somma cumulativa (il segno +=) era la prima cosa che avevo provato, anche io pensando che fosse lo strumento che facesse per me.

Ma non funziona.

Al posto di aumentare sequenzialmente, la quota bersaglio segue passo a passo la posizione dello stick della manetta. Quando la manetta arriva in cima, la quota smette di crescere. Idem per l'altro estremo.

Forse nel tuo codice hai qualche istruzione che riporta il Setpoint al valore iniziale prima di sommargli il valore dello stick della manetta ?

Se si, ovvio che non funziona, perchè ad ogni ciclo, resetta il Setpoint e gli somma solo il valore attuale senza considerare l'aumento che avevi già dato prima.

Posta se vuoi/puoi il codice così vediamo

No… non annullo il lavoro fatto, riscrivendo sopra a Setpoint.
La somma cumulativa sta DOPO la definizione della variabile setpoint. Quindi prima la definisco, poi la riempio del valore numerico che volgio, e poi provo invano ad incrementarla.

Comunqune ecco il codice. Verso la fine ci sono dei commenti a forma di freccia. Quello è il nucleo del problema.

Proprio non capisco.

/*
Author: Marco
Version: 8 July 2015, Aachen

Altitude Hold Sketch For QuadCopter using BMP Pressure sensor. 
*/

// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL  Analog 5
// Connect SDA to Analog 4

//Include LIbraries
#include <Wire.h> 
#include <Adafruit_BMP085.h>
#include <Servo.h> 
#include <Average.h> 
#include <PID_v1.h>


Adafruit_BMP085 bmp;



//PArametri per il filtro
const int c = 5;
double readings[c];      // the readings from the analog input
double setp[c];      // the readings from the analog input
int index = 0;                  // the index of the current reading
double total = 0;                  // the running total
double average = 0;                // the average


int k=0;   
int S=0;


//Parametri di Servizio
Servo manetta;       //dai un nome all'ogetto
int ch3;             //channel used to switch the control on and off
int ch6;             //throttle input channel
int testTR=1400;     //static throttle value (used for earlier test version)
//Define PINs on Arduino Board (uno)
int PinSwitch=10;    //Switch
int PinIn=7;         // Signal enter into arduino from radio RX
int PinOut=9;        // Signal leave arduino and goes to quadcopter
int led = 13;        //Led to detect on off 


int jj=0;

double Oldpress;

//Set PID Parameters
double Setpoint, Input, Output;

//double Kp=10, Kd=2.5, Ki=0; //Test 1;
  double Kp=10, Kd=0, Ki=1; //Test 2;


//Specify the links and initial tuning parameters
PID AltHold(&Input, &Output, &Setpoint,Kp,Ki,Kd, DIRECT);



void setup() 
{
    manetta.attach(PinOut);
    pinMode(PinIn, INPUT);
    pinMode(led, OUTPUT); 
    pinMode(PinSwitch, INPUT); 
    Serial.begin(115200); // Pour a bowl of Serial
    if (!bmp.begin()) 
    {
 Serial.println("Could not find a valid BMP085 sensor, check wiring!");
 while (1) {}
    }
    Serial.println("");
    Serial.println("");
    Serial.println("");
    
   //Store first value    
   double p;
   p=bmp.readAltitude(102000);
   Oldpress=p;
}




void loop() 
  {
      int j=0; //counter
      
      ch6 = pulseIn(PinSwitch, HIGH, 20000);
      
      double p;
      p=bmp.readAltitude(102000); //quota di Riferimento 1020 hPa

      
      //Media Mobile
      total= total - readings[index];          
      readings[index] =p; 
      total= total + readings[index];  

      
      index = index + 1;                    
      if (index >= c)              
          index = 0;                           
          average = total / c;         
        

      Serial.print(average,3);
      
      //Booleano per lettura pressione e definire Setpoint
      boolean bAltitudeStored=false;


      //Decidi in che modalità volare. 
      // Switch (ON or OFF),     
      if (ch6<1100) //Manual Flight
          {
            //Lettura PRessione
            bAltitudeStored=false;
                 if (!bAltitudeStored)
                {
                   Oldpress=average;
                }
           
                ch3 = pulseIn(PinIn, HIGH, 20000);
                Serial.print("  Throttle:");
                Serial.print(ch3);
                Serial.print("\t (MANUAL)");
                if (ch3<1060){Serial.print("\tIdle");};
                if (ch3>1900){Serial.print("\tFull");};
                //Serial.println();
                manetta.writeMicroseconds(ch3); 
                digitalWrite(led, LOW);   // 
                
            
          }
        else  //Altitude Hold
          {


               bAltitudeStored=true;
               if (!bAltitudeStored)
                {
                 Oldpress=average;
                }
    
                Setpoint=Oldpress; //<----Pressione usata come setpoint  
                Input=average;    //<-----misura di pressione (quota)
                
                float xx, yy;
                ch3 = pulseIn(PinIn, HIGH, 20000);
                xx=constrain(ch3,1200,1900);
                yy=map(xx,1200,1900,-10,10); //<---- questo è il valore mappato e "spianato" nel mezzo che rispecchia la manetta
                
    
                if (yy >= -5 && yy <= 5){yy=0;}
                yy=yy/8;
                
                //Questa è la parte che non funziona. Perchè non accumula? 
                Setpoint+=yy;
            
            
            
            //TManetta e sua mappatura            
            float x, Thr1, Thr2;
            x=constrain(Output,0,15);
            Thr1=map(x, 0, 15, 1200, 1550);
            Thr2=Thr1+160; 
            Thr1=Thr2;            
            manetta.writeMicroseconds(Thr1);
            
            
            //PID
            AltHold.SetSampleTime(10);
            AltHold.SetMode(AUTOMATIC);
            AltHold.Compute();
            
            
            
            //Stampa su terminale
            Serial.print("\t (Alt. Hold)");
            digitalWrite(led, HIGH);
            Serial.print("\t Setpoint:");
            Serial.print(Setpoint);
            Serial.print("\t Output:");
            Serial.print(Output);
            Serial.print("\t Throttle Input:");
            Serial.print(Thr1);       
            Serial.print("\t yy:");
            Serial.print(yy, 3);         
            Serial.print("\t Kp:");
            Serial.print(Kp);  
            Serial.print("\t Ki:");
            Serial.print(Ki);  
            Serial.print("\t Kd:");
            Serial.print(Kd);  
          };
    
    Serial.println("");   
    delay(10); 
}

Se tu assegni un valore cosi

Setpoint=Oldpress; //<----Pressione usata come setpoint

prima di fare il

Setpoint+=yy;

fai la somma di yy e al prossimo loop riporti Setpoint al valore iniziale e gli (ri)sommi il valore di yy dell’attuale loop, ma così hai perso il valore di yy del loop precedente… esempio numerico

Setpoint = Oldpress; //Dove Oldpress = 100 ed è il numero d'esempio che ho scelto di assegnare a Oldpress
yy = 1; //sempre un valore d' esempio
Setpoint+=yy; //Setpoint varrà 101 !

al prossimo loop facciamo che yy assuma il valore di +1 ancora…tu ti aspetti di avere un Setpoint di 102 dunque giusto ? ma hai la riga

Setpoint = Oldpress; //Dove Oldpress è ancora 100
yy = 1;
Setpoint+=yy; //Setpoint varrà sempre 101 !

Quindi ovvio che non funziona come vorresti! Setpoint = Oldpress; lo devi fare solo una volta prima di iniziale a sommare i valori di yy!

Ciao!

Hai ragione: come ho fatto a non vedere una patacca del genere?!

Ora funziona perfettamente. Grazie.
Ora ho un altro probelma ma apro un’altro thread.

ciao.
M

[....]
      else  //Altitude Hold
          {
          
           //quando attivo lo swith smetti di aggiornare il valore di pressione e mantieni l'ultimo letto.
           bAltitudeStored=true;
           if (!bAltitudeStored)
              {
                   Oldpress=average;
                   Setpoint=average;
              }
            Setpoint=Oldpress ;
            Input=average;
            
            float xx, ddz, dz;
            ch3 = pulseIn(PinIn, HIGH, 20000);
            xx=constrain(ch3,1250,1900);
            ddz=map(xx,1250,1900,-1,1);
            if (ddz >= -0.85 && ddz<=0.4 ){ddz=0;}       //zona morta in un ventaglio centrale 

            
            dz+=0.1*ddz;                        // riduce l'incremento di un fattore 10.   
            Oldpress=Oldpress+dz;             //  somma cumulata