Pages: 1 [2]   Go Down
Author Topic: plot grafico tramite processing real time  (Read 2363 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, ho capito tutto fino al byte gratis che si guadagna, dopo mi sono perso. ti mando un mess privato
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ah ok, se cambi il prescaler cambia la velocità dell'analogRead, e quindi è giusto che il tempo di "posticipazione" diminuisce.

per rendere il codice più veloce usa la write() invece che la pritn(): la print converte in caratteri ascii, ovvero 1 byte per ogni cifra; con la write scrivi in maniera binaria, quindi scrivi tanti byte quanto la dimensione della variabile.

Cole prescaler a 16 hai una precisione a 8 byte, quindi puoi prendere sono gli 8 byte più significativi (sui 10 che ti restituisce l'analogRead) e quindi aresti un byte per lettura.

Però devi inventarti un sistema per sincronizzare i dati.

a casa ho del codice sia per inviare che per ricevere, ma devo upparlo sul repo. Se hai facebook, ho postato

ok, fino qui ho capito,
Quote
del codice che fa 3 letture analogice (a scelta a 10 o 8 bit di precisione), nel caso di 8 bit le invio dirette al PC, nel caso di 10 bit, faccio la lettura dei 3 dati in un array, poi anzichè inviare 6byte (2 byte per letura, un int) unisco i dati per fare in modo di usare solo 4 byte (4*8=32bit, avanzano 2 bit a scrittura, in teoria facendo un array di 30 elementi guadagni un byte "a gratis" sfruttando anche quei due bit)

il trucco si sincronizzazione è che l'arduino andava in loop finchè processing,. quando pronto a ricevere, inviava un comando.

uesto perchè se inizi a legegre il flusso seriale in un momento a caso non sai il byte che stai leggendo a che misurazione si riferisce, e nel caso di invio di più di un byte a varibaile (da int in su) non sai nemmeno se il byte che hai letto è la parte bassa o la parte alta.
questa partte invece mi è un po' oscura  smiley-mr-green soprattutto la fine.
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10502
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se prendiamo 10 bit per lettura (risoluzione max ADC), abbiamo 30 bit.
se prendiamo 4 byte ("risoluzione" min seriale), abbiamo 32bit. Quindi possiamo mettere 3 letture ADC in 4 byte! ma sprechiamo 2 bit a volta.

Se volessimo usare anche questi 2 bit, basta vedere ogni quante scritture abbiamo accumulato abbastanza "2bit" da fare 10 bit:
10/2=5scitture di 3 valori (avvero 4 byte)

quindi ogni 5*3=15 letture, ovvero 5*4=20byte scritti, abbiamo accumultao abbastanza 2bit per farci stare una lettura ADC.

Quindi il messaggio finale usa 20 byte e conterrà 16 letture invece che 15!

di seguito vedi come le letture di A, B e C (3 letture ADC a 10 bit) vengono posizionate nei primi 3 byte. nota come  se ne fregano altamente della suddivisione in byte del messaggio; dunque ogni invio è assolutamente legato al precedente e necessita di un poco di gioco di bit-shift.
io ho preferito perdere 2 bit e creare il messaggio corto, ovvero di 3 letture.

In realtà per non perdere nessun bit il messaggio deve essere lungo multipli di 5byte (il 20  calcolato prima non è ottimizzato smiley ), infatti 5byte*8bit = 40bit, perfetti per contenere 40bit/10bit/lettureADC=4lettureADC
( bit/lettureADC è il "dimensionamento" della variabile, ovvero numero di bit fratto lettura ADC, tardotto in lingua corrente vuol dire bit necessari per lettura ADC)

1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 _ 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 _ 17 - 18 - 19 - 20 - 21 - 22 - 23 - 24
a   a   a    a   a   a   a   a    a    a    b     b     b     b     b    b      b     b      b    b   c      c    c      c

NOTA: se usi solo gli 8bit più signifacativi a lettura, abbiamo che i bit ADC sono == ai bit utili via seriale, dunque questo casino assurdo non è necessario da fare


Per la sincronizzazione, abbiamo 3 byte (da 1 a 8, da 9 a 16, da 17 a 24), e per decodificare l'informazione bisgna avere per forza i dati a parteire dal primo byte fino a fine messaggio (che può essere lungo 4,5,20 byte a secondaa del valore che hai scelto per comprimere il più possibile).
Immagina che arduino inizia a leggere e sparare i dati via seriale al pc. finchè il programma lato PC non è attivato, i byte vengono persi nel nulla galattico (/dev/null, se sei linuxiano). Quindi la tua applicazione parte e gli arriva un byte. questo byte è forse l'inizio della sequenza? o quello di mezzo? o quello finale?
se invece usi L'ADC a 8 bit, sai che ogni byte che ti arriva è una lettura e non devi decodificarla, però nel caso tu faccia letture su più pin, o con significato differente, questa lettura cosa rappresenta? la lettura sul pin A0, quella sul pin A2, etc..?
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

per non complicarmi troppo la vita per il momento ho deciso di lasciare la risoluzione a 8bit, vorrei provare però a cambiare strategia mettendo i dati prima in alcuni array e poi a stamparli, il problema è che dopo che accendo il relay, non succede niente, non mi stampa niente.
non mi sembra che il codice sia sbagliato.
i due array bidimensionali fungono da tabelle: nella prima colonna ci sono i valori di tensione misurati, nella seconda colonna ci sono i tempi a cui avvengono le misure. il principio è di riempire gli array con un numero x di misure e poi ordinare i risultati in ordine crescente dei tempi, ma ripeto, non ho alcun output.
qualcuno riesce a vedere il problema?


Code:
#define RELAY_PIN 3 //digital pin to control the relay
#define c_pin A1    //capacitor analog pin
#define ps_pin A0  //power supply analog pin
#define num_misure 50

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif



void setup()
{
  // set prescale to 16
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;

  pinMode(RELAY_PIN, OUTPUT);
  Serial.begin(9600); // open serial
  Serial.println("Press the spacebar to start to measure");
}


void loop()
{
  static int relayVal = 0;
  int cmd;
  float c_voltage, ps_voltage, current;
  static float res = 3.59;
  unsigned long time1, time2, time0;
  float PS_VOLTAGE[1000][2];  // these two arrays are tables in which we put the voltage
  float C_VOLTAGE[1000][2];   // measurements and the time arduino took em
  float CURRENT[1000];
  int j = 0;

  while(Serial.available() > 0)
  {
    cmd = Serial.read();

    switch(cmd)
    {
    case ' ':
      {
        relayVal ^= 1;
        Serial.println("Relay on");
        break;
      }
    default:
      {
        Serial.println("Press the spacebar to start to measure");
      }
    }




    if(relayVal)
    {       
      do{
        digitalWrite(RELAY_PIN, HIGH);
        delay(20);            // relay transition time ---------- problema, ho impostato questo ritardo
        // per aspettare la commutazione del relay, ma questa non è tempocostante

        time0 = micros();     // time the measure start
        do
        {

          c_voltage = analogRead(c_pin);
          time1 = micros()-time0; //time c_voltage measurement
          ps_voltage = analogRead(ps_pin);
          time2 = micros() - time0; //time ps_voltage measurement

          c_voltage = c_voltage *5 /1023;
          ps_voltage = ps_voltage * 5 / 1023;
          current = (ps_voltage - c_voltage)/res;

          //put all the measurements in their arrays
          PS_VOLTAGE[j][0] = ps_voltage;
          PS_VOLTAGE[j][1] = time1;     
          C_VOLTAGE[j][0] = c_voltage;
          C_VOLTAGE[j][1] = time2;
          CURRENT[j] = current;
          j++;
        }
        while(current >0.000001);

        //capacitor discharge
        digitalWrite(RELAY_PIN, LOW);
        do
        {
          c_voltage =  analogRead(c_pin);
          c_voltage =  c_voltage * 5 / 1023;         
        }
        while(c_voltage > 0.001);

      }
      while( j <= num_misure - 1 );

      /*
      ordinamento vettori in base ai tempi per sincronizzare le misure
       */

      j= 0;

      //stampa risultati
      for ( j = 0; j < num_misure - 1; j++)
      {
        Serial.print(PS_VOLTAGE[j][0]);
        Serial.print("  ");
        Serial.println(PS_VOLTAGE[j][1]);
      }



      relayVal = 0; //reitialize relayVal

      Serial.print("\n\n");

      Serial.print("do you want to repeat the measure?");
    }


  }   
}
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10502
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
c_voltage = c_voltage *5 /1023;
          ps_voltage = ps_voltage * 5 / 1023;
è corretto, ma meglio mettere delle parentesi, è più leggibile e eviti errori stupidi di precedenza

Code:
while(current >0.000001);
uhmm valore moooolto basso, probabile problema n°1. Ricorda che il pin non è a GND ma floattante, quindi mi aspetto di leggere valòori random. A priori metti come limite di NON sfondare l'array:
Quote
while(current >0.000001 && j < 1000);

poi
Code:
while(c_voltage > 0.001);
probabile errore n°2, ma almeno non sfondi array smiley


poi non capisco:
Code:
while( j <= num_misure - 1 );
perchè? non capisco bene il ragionamento


dolcis in fundo:
Code:
c_voltage = analogRead(c_pin);

attenzione, l'analog read restituisce un int, ovvero due byte, di cui ti interessando 10 bit:
0 1  2 3 4 5 6 7 - 8 9 A B C D E F
N N N N N N S S   S S S S S S  L  L

come puoi vedere i bit N sono NON usati. Gli S sono quelli importanti, ovvero quelli che variano di più il valore della variabile, e quelli con L sono unità (F) e decine (E) (in binario eh), quindi sono i meno importanti.

tu stai salvando i bit da 8 a F:
Code:
c_voltage = analogRead(c_pin);

invece devi eliminare i due bit L in modo da prendere solo quelli interessanti:
Code:
c_voltage = (analogRead(c_pin) >> 2);

il >> sigfnica proprio "sposta i bit 2 volte a sinistra" (la parte che rimane "vuota" diventa 0)
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
Code:
while(current >0.000001);
uhmm valore moooolto basso, probabile problema n°1. Ricorda che il pin non è a GND ma floattante, quindi mi aspetto di leggere valòori random. A priori metti come limite di NON sfondare l'array:
while(current >0.000001 && j < 1000);
è sicuramente l'errore che commettevo infatti adesso va

Quote
poi non capisco:
Code:
while( j <= num_misure - 1 );
perchè? non capisco bene il ragionamento
mi ero dimenticato di sostituire num_misure a 1000


Quote
dolcis in fundo:
Code:
c_voltage = analogRead(c_pin);

attenzione, l'analog read restituisce un int, ovvero due byte, di cui ti interessando 10 bit:
0 1  2 3 4 5 6 7 - 8 9 A B C D E F
N N N N N N S S   S S S S S S  L  L

come puoi vedere i bit N sono NON usati. Gli S sono quelli importanti, ovvero quelli che variano di più il valore della variabile, e quelli con L sono unità (F) e decine (E) (in binario eh), quindi sono i meno importanti.

tu stai salvando i bit da 8 a F:
Code:
c_voltage = analogRead(c_pin);

invece devi eliminare i due bit L in modo da prendere solo quelli interessanti:
Code:
c_voltage = (analogRead(c_pin) >> 2);

il >> sigfnica proprio "sposta i bit 2 volte a sinistra" (la parte che rimane "vuota" diventa 0)
questo non ho capito a cosa mi serve: questo secondo controllo mi serve solo a fare un check sul fatto che la misura può riprendere solo quando il condensatore è scarico, a che mi serve spostare il tutto di 2 bit?


cmq adesso va, ma riscontro uno strano comportamento: finchè num_misure <=200 il tutto procede liscio, appena aumento il num_misure e quindi la dimensione dell'array va tutto a farsi benedire, quindi mi chiedo:c' è un limite di grandezza di un array che arduino può processare? questo limite è 200?
« Last Edit: October 30, 2012, 03:36:36 am by aureliusss » Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mi sono dato una risposta
http://www.arduino.cc/playground/Main/CorruptArrayVariablesAndMemory#Max_size_of_array
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10502
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sapevo deil limite della ram ma non avevo mai visto un aricolo così completo, complimenti, ora ho imparato qualcosa anche io smiley
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Pages: 1 [2]   Go Up
Jump to: