funzione micros() con processing -- comunicazione seriale

ciao a tutti, vorrei sapere se c'è un modo per usare la funzione micros() di arduino programmato tramite processing.
mi spiego meglio: devo misurare la curva di carica e scarica di un condensatore, dunque, siccome la funzione millis() non è abbastanza "risoluta" ho chiamato la funzione micros() per triggerare l'istante iniziale e tutti gli altri istanti.

ora vorrei riscrivere il codice per processing così da poter plottare a video il grafico, ma a quanto ho visto processing riconosce solo la funzione millis().

duqneu tornando alla domanda principale: c'è un modo per richiamare la funzione micros() di arduino tramite processing?

P.S. sto lavorando con Arduino UNO Rev3, Arduino IDE 101, Processing 2.05, windows7

Io non ho capito bene, hai un arduino che parla con processing tramite seriale e vuoi visualizzare il grafico in tempo reale?

no, non ho la necessità di visualizzare il grafico il tempo reale, ma per prendere più punti di misura sulla caratteristica, utilizzo la funzione micros() di arduino. esiste un equivalente o un modo per farlo con processing?

Non puoi passare i valori che prendi da arduino con la funzione micros e passarli a processing allora? Non ti servi comunque dell'arduino per catturare i valori di Vc nel tempo?

Spiega meglio come stai trasferendo i dati dal Aruino al PC.
Ciao Uwe

questo il codice che ho scritto per arduino:

#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 65

// 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 int time1, time2, time0;
  unsigned long int PS_TIME[num_misure], C_TIME[num_misure];
  float PS_VOLTAGE[num_misure], C_VOLTAGE[num_misure], CURRENT[num_misure];
  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)*1000)/res; // to obtain mA

          //put all the measurements in their arrays
          PS_VOLTAGE[j] = ps_voltage;
          PS_TIME[j] = time2;     
          C_VOLTAGE[j]= c_voltage;
          C_TIME[j] = time1;
          CURRENT[j] = current;
          j++;
          delayMicroseconds(1380);
        }
        while(current >0 && j < num_misure);

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

      }
      while( j <= num_misure - 1 );

      //stampa risultati
      Serial.println("  PS_VOLTAGE");
      
      for ( j = 0; j < num_misure ; j++)
      {
        Serial.print(PS_VOLTAGE[j]);
        Serial.print("  ");
        Serial.println(PS_TIME[j]);
      }
      
      
      j=0;
      Serial.println("\n\n  CURRENT");
      for ( j = 0; j < num_misure ; j++)
      {
        Serial.println(CURRENT[j]);
        }
      
      Serial.println("  C_VOLTAGE");
      
      for ( j = 0; j < num_misure ; j++)
      {
        Serial.print(C_VOLTAGE[j]);
        Serial.print("  ");
        Serial.println(C_TIME[j]);
       }
       



      
      
      relayVal = 0; //reitialize relayVal

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

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


  }   
}

diciamo che è stato il primo step, funziona così: attivo il relè premendo la spacebar, attivando il relè collego il generatore di tensione al condensatore che si carica, salvo i valori in vari array e poi li visualizzo sul monitor seriale.

ora, dato che è abbastanza grezzo visualizzare i dati su seriale vorrei poter plottare il grafico a video usando processing.

leggendo in giro ho scoperto firmata, quindi uploadando standard firmata su arduino, dovrei poter scrivere il codice corrispondente con processing per poi ottenere i grafici corrente-tensione, tensione-tempo. quindi esiste un modo per usare micros() con processing?

spero di essermi spiegato

quello che vuoi fare è fondamentalmente errato. Quello che andresti a misurare non è la scarica del condensatore ma il tempo di comunicazione della seriale. Mica crederai che la comunicazione è istantanea?! al contrario! con 9600 baud hai 960 caratteri al secondo, quindi poco più di 1ms per scrivere una lettera!

Quindi la soluzione è di inviare un comando ad arduino che effettua in modo completamente autonomo la misura e poi la ritorna a processing una volta conclusa.

Firmata, visto che usa la seriale per inviare il codice dal PC ad arduino istruzione per istruzione in "real time", è in realtà lentissimo proprio a causa di questa limitazione.

certo puoi dirmi che puoi aumentare il baudrate, ma se hai bisogno di tempi di risposta nell'ordine del microsecondo allora il fatto di leggere dei comandi da Seriale, interpretarli ed eseguirli è un peso assurdo in confronto ad eseguire dei comandi già compilati in codice nativo.

edit: BTW processing non possiede una funzione al di sotto dei millis, per il semplice fatto che molti (vecchi) timer di PC accessibili lato utente non scendono al di sotto dei 10 millisecondi: i tempi sono basati sull'RTC che non ha un clock molto elevato. Poi in realtà i PC moderno usano altre serie di timer "ad alta velocità" che permettono ri raggiungere la precisione del nanosecondo.

Passare da processing a java è semplice, e avari a diosposizione una serie molto più vasta di instruzioni.

dunque l'approccio che sto usando è sbagliato, perfetto! =(
ripartendo dall'inizio allora:
-arduino prende le misure e le memorizza negli array;
-arduino passa questi array a processing;
-processing plotta gli array;

ora, come eseguo il passaggio degli array da arduino a processing?

edit: si tratterebbe forse di importare via seriale i dati che ho e questi dati li faccio ''analizzare'' da processing

con un loop scrivi i dati dell'array, e con un altro loop li leggi... esattamente come fai ora per un valore singolo.

non ho capito cosa intendi: in processing dovrei usare un loop per leggere i dati che sono scritti su seriale e con un altro loop li metto in un altro array che analizzo per la visualizzazione?

Raccogli i dati relativi al condensatore dall'arduino e li memorizzi in un array o meglio ancora in una matrice(C[Vc][t] ad esempio) e una volta concluse le misure li mandi con un loop sulla seriale in tutta tranquillità e da processing leggi il valore sempre con un loop.
Ovviamente dietro la parola 'loop' ci sono doversi significati, i dati li raccogli in maniera più o meno diversa a seconda del formato e del tipo..

ho scritto questi due codici di prova, ma l'output che ricevo non lo capisco:
codice arduino:

int val;

void setup(){
  Serial.begin(9600);
}

void loop(){
val = analogRead(0);//collegato al pin centrale di un potenziometro
Serial.print(val);
Serial.print("\n");
delay(1000);

}

codice processing:

import processing.serial.*;
String val;
Serial commport;

void setup() {
  size(200, 200);
  commport = new Serial(this, "COM6", 9600);
  commport.write(65);
}

void draw() {
}

void serialEvent(Serial port) {

    val = commport.readStringUntil('\n');

    println("raw input:" + val);
  }

sulla ''console'' di processing questo è l'output che ricevo:

...raw input:null
raw input:null
raw input:null
raw input:753
...

ricevo tanti null quante sono le cifre del numero

edit:
ho modificato il codice arduino richiamando la funzione Serial.available in questo modo:

if (Serial.available > 0)
  {
    Serial.read();
    val = analogRead(0);
    Serial.print(val);
    Serial.print("\n");
    delay(1000);

  }

ma in compilazione mi da un errore che non avevo ancora visto :error: invalid use of member (did you forget the '&' ?)

L'errore probabilmente è dato dal fatto che manca "()" dopo available, essendo una funzione.
Suppongo tu abbia messo quella conduzione per capire quando apri processing visto che mandi quel valore all'inizio..

Comunque questa cosa antipatica del null è capitata anche a me e non riuscendone a capire l'origine ho messo un filtro su processing del tipo if(val!= 'null') e via, tanto a te dopo qualche null ti arriva qualche valore atteso no?

sciorty ha ragione lato arduino, e spero che tu ti renda conto che in quel caso arduino ti scrive un messaggio solo se prima legge un qualsiasi carattere sulla seriale

lato java il "null" è il valore che indica il vuoto, ovvero che un oggetto non è stato inizializzato.

questo vuol dire che il tuo serialEvent viene chiamato, ma tra i dati raccolti fino a quel momento non viene trovato uno \n, e infatti quando lo \n arriva processing stampa il valore.

esistono vari sistemi per aggirare la cosa.

ok, grazie a tutti, ora sulla seriale ho finalmente l'output giusto, nel senso che la condizione su null funziona.
ora però mi sorge un altro problema: non riesco a convertire la stringa in numero.
Ho provato a usare sia string.parseInt che Integers.valueOf(string).intValue() ma genera un eccezione

secondo voi mi conviene scompattare la stringa in array di caratteri e poi usare il parseInt o parseFloat?

int num = Integer.parseInt(stringa);
(però è java, on ricordo se va anche in processing)

niente, ho provato ma genera un'eccezione causata dall aver letto come valore '0'

edit: ho provato anche ad usare la funzione int(string) ma mi restituisce il valore zero

mostra il codeice si errore, probabilmen quello non è no zero ma uno spazio+zero o simili (\n, \r, \t etc..), e quindi va in errore. fai così:
int num = Integer.parseInt( stringa.trim() );
dovrebbe funzionare nella maggior parte dei casi sopracitati.

sono riuscito ad impostare la comunicazione, ma adesso ho un problema lato processing:
invio i dati da arduino a processing con successo, ma non riesco a salvarli negli appositi array per poi analizzarli e plottarli
questo il serialEvent di processing

void serialEvent(Serial port) {
  measure = commPort.readStringUntil('\n'); //leggo l'intera stringa con i dati, divisi da virgole

  int i=0; //contatore per scorrere gli array
  if (measure != null) {

    String[] valori_misura = new String[5];
    valori_misura = split(measure, ","); //divido la stringa in cinque parti(sono  i cinque i dati che ricevo)

    ps_voltage = parseFloat(valori_misura[0].trim()); //trasformo il valore da stringa a float
    PS_VOLTAGE[i]=ps_voltage; //metto il valore così letto nell'array

    c_voltage = parseFloat(valori_misura[1].trim());
    C_VOLTAGE[i] = c_voltage;
    
    current = parseFloat(valori_misura[2].trim());
    CURRENT[i] = current;
 
    ps_time = parseInt(valori_misura[3].trim());
    PS_TIME[i] = ps_time;
 
    c_time = parseInt(valori_misura[4].trim());
    C_TIME[i]=c_time;

    i++; //aggiorno l'indice dell'array
  }
}

con questo codice pensavo di poter fare riuscire a salvare i dati negli array, ma se faccio una semplice prova di stampa vedo che salva un'unico valore per tutto l'array.