Offline
Jr. Member
Karma: 1
Posts: 83
|
 |
« on: October 24, 2012, 07:15:22 am » |
ciao a tutti, ho già scritto un post (sezione hardware) su un primo lavoro di tesi che sto facendo: rilevare la caratteristica corrente tensione di un alimentatore. http://arduino.cc/forum/index.php/topic,126840.0.htmldopo aver implementato questo circuito su breadboard  con il codice corrispondente per rilevare tensioni e corrente #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
void setup() { pinMode(RELAY_PIN, OUTPUT); Serial.begin(9600); // open serial Serial.println("Press the spacebar to toggle relay on/off"); }
void loop() { static int relayVal = 0; int cmd; float c_voltage, ps_voltage, current; static float res = 5.2; while (Serial.available() > 0) { cmd = Serial.read(); switch (cmd) { case ' ': { relayVal ^= 1; // xor current value with 1 (causes value to toggle) if (relayVal) Serial.println("Relay on"); break; } default: { Serial.println("Press the spacebar to toggle relay on/off"); } } if (relayVal) { digitalWrite(RELAY_PIN, HIGH); delay(20); // relay transition time do { c_voltage = analogRead(c_pin); ps_voltage = (analogRead(ps_pin)); c_voltage = c_voltage *5 /1023; ps_voltage = ps_voltage * 5 / 1023; current = (ps_voltage - c_voltage)/res; Serial.print(ps_voltage); Serial.print(" "); Serial.print(c_voltage); Serial.print(" "); Serial.print(current); Serial.print("\n"); } while(current >0.000001); Serial.println("Please wait for the capacitor to discharge"); digitalWrite(RELAY_PIN, LOW); do { c_voltage = analogRead(A1); c_voltage = c_voltage * 5 / 1023; Serial.println(c_voltage); delay(50); // just a delay to not print all the values } while(c_voltage > 0.001); relayVal = 0; // reinitialze the relayVal Serial.println("\nThe relay is off, press the spacebar"); Serial.println("again if you want to repeat the measure\n"); }
} }
vorrei riuscire a plottare in real time i dati che ricevo su corrente e tensione tramite processing. ho letto tutti i vari post qui sul forum che riguardano processing e visto anche qualche tutorial, ma non ho trovato come fare a prendere le due serie di dati e plottarli in un semplice grafico tipo questo ottenuto con excel  grazie per l'aiuto
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 15
Posts: 1889
Have you mooed today?
|
 |
« Reply #1 on: October 24, 2012, 07:28:01 am » |
Ciao, prova a dare un'occhiata a questo progetto: http://code.google.com/p/arduinoscope/dovresti trovare tutti gli strumenti che ti servono per realizzare il tuo progetto 
|
|
|
|
|
Logged
|
|
|
|
|
Bergamo
Offline
God Member
Karma: 1
Posts: 585
|
 |
« Reply #2 on: October 24, 2012, 07:44:58 am » |
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 83
Posts: 8239
:(){:|:&};:
|
 |
« Reply #3 on: October 24, 2012, 09:22:41 am » |
leggi i dati dalla seriale e li metti in un ArrayList. Questo arrayList va sempre usato in un blocco syncronize(nomeArrayList){ //ora puoi usare in sicurezza l'arrayList }
Questo è necessario perchè l'acquisizione su seriale e il disegno sono su due thread diversi; usare una line per ogni valore seriale manderebbe in palla la grafica, che non riuscirebbe a disegnare abbastanza in fretta, mentre usare un array non sincronizzato può creare dei casini si concorrenza esagerati
ogni draw() scorri gli ultimi A valori dell'arraylist (dove X è la scala lungo l'asse X) e poi disegni delle righe col comando line(X1, Y1, X2, Y2);
dove Y1 è il valore attuale, Y2 il prossimo valore, X1 e X2 un valore che si incrementa di Tot, dove tot è la larghezza della finestra diviso A
se vuoi disegnare più righe, basta ripetere questa parte del codice, sommando una costante ad Y per evitare che i dati si sovrappongano (se non vuoi la sovrapposizione) facendo attenzione anche a non uscire dallo schermo!
sempre per non uscire dallo schermo, probabilmente dovrai usare uno zoom anche sull'asse Y, ovvero tutti i valori di Y moltiplicarli per B, esattamente come quelli di X li ai divisi per A
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 83
|
 |
« Reply #4 on: October 24, 2012, 09:54:20 am » |
scusate ragazzi, il professore mi ha chiesto di mofificare lo sketch che ho sopra scritto, per avere più misure e visualizzare anche il tempo a cui vengono effettuate le misure, impostando come t=0 l'istante in cui inizio l'acquisizione dei dati? coem faccio a impostare un cronometro? e che ''risoluzione'' può avere questo cronometro secondo voi?
|
|
|
|
|
Logged
|
|
|
|
|
Bergamo
Offline
God Member
Karma: 1
Posts: 585
|
 |
« Reply #5 on: October 24, 2012, 10:10:26 am » |
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 83
|
 |
« Reply #6 on: October 24, 2012, 10:58:13 am » |
secondo voi come potrei aumentare il numero di misure effettuate? esiste un modo per aumentare la frequenza dell'analogRead?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 83
Posts: 8239
:(){:|:&};:
|
 |
« Reply #7 on: October 24, 2012, 11:04:01 am » |
sì, diminuendo il prescaler. Però diminuisce anche la precisione della lettura, se non erro a 16 (il prescaler di defautl mi pare sia sui 128) ha una precisione a 8bit se non meno (cioè, i valori "reali" vanno da 0 a 255, il resto è rumore, anzichè i classici 10bit da 0 a 1023)
|
|
|
|
|
Logged
|
|
|
|
|
|
|
0
Offline
Tesla Member
Karma: 83
Posts: 8239
:(){:|:&};:
|
 |
« Reply #9 on: October 24, 2012, 12:44:36 pm » |
esatto
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 83
|
 |
« Reply #10 on: October 29, 2012, 10:04:49 am » |
ma con il codice che ho scritto, anzi esattamente questo segmento: c_voltage = analogRead(c_pin); time1 = micros()-time0; //time c_voltage measurement ps_voltage = analogRead(ps_pin); time2 = micros() - time0; //time ps_voltage measurement
secondo voi time1 e time2 che poi andrò a stampare, sono esattamente il tempo in cui arduino prende la misura o sono posticipati?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 83
Posts: 8239
:(){:|:&};:
|
 |
« Reply #11 on: October 29, 2012, 10:11:15 am » |
posticipati, direi di circa 204microsecondi (200 microsecondi di lettura + 4 microsecondi per la nuova richiesta di micros)
essendo un valore fisso, di solito si può ignorare senza conseguenze, semplicemente il grafico è sballato di 200 micros sull'asse del tempo (se prendi come riferimento l'inizio lettura, se prendi la fine lettura sei quasi perfetto)
|
|
|
|
« Last Edit: October 29, 2012, 10:12:47 am by lesto »
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 83
|
 |
« Reply #12 on: October 29, 2012, 10:27:59 am » |
possibile che siano addirittura posticipati di 204 microsecondi? forse ho sbaglaito a non postarvi tutto il codice, perchè da quello che vedo io in output ad esempio, la prima misura sul c_voltage avviene al tempo di 20us #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 // 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("How many measure do you want to take?"); }
void loop() { int num_misure; float c_voltage, ps_voltage, current; static float res = 3.59; unsigned long time1, time2, time0; int i ; if(Serial.available() > 0) { num_misure = Serial.parseInt(); // Arduino stream function which receive a string on the serial port and then changes it int an integer if(num_misure > 0) { for(i = 1 ; i <= num_misure; i++) { Serial.print("Misura n."); Serial.println(i); digitalWrite(RELAY_PIN, HIGH); delay(20); // relay transition time::::::: problema, ho impostato questo ritardo per aspettare la commutazione del ralay, ma questo non ha un tempo fisso 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; Serial.println(ps_voltage); Serial.println(time1); Serial.println(c_voltage); Serial.println(time2); Serial.println(current); Serial.print('\n'); } while(current >0.000001); Serial.println("Please wait for the capacitor to discharge"); digitalWrite(RELAY_PIN, LOW); do { c_voltage = analogRead(A1); c_voltage = c_voltage * 5 / 1023; Serial.println(c_voltage); delay(50); // just a delay to not print all the values } while(c_voltage > 0.001); Serial.print("\n\n"); } } }}
l'ho modificato rispetto a quello postato prima settando il prescaler a 16 come mi avevi descritto anche tu l'output che ho è questo:(lo posto come codice èper renderlo leggibile) How many measure do you want to take? Misura n.1 2.65 32 1.01 48 0.46
2.74 1592 1.03 1612 0.48
2.83 3332 1.11 3352 0.48
3.83 25316 2.09 25336 0.49
5.00 59636 3.58 59656 0.39
5.00 93956 4.86 93976 0.04
5.00 128280 5.00 128296 0.00
Please wait for the capacitor to discharge 5.00 1.64 0.47 0.13 0.01 0.00
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 83
|
 |
« Reply #13 on: October 29, 2012, 10:34:55 am » |
inoltre vorrei eliminare quella serie di Serial.print() per aumentare i ''punti'' di misura avrei pensato alla costruzione di tre array PS_VOLTAGE[], C_VOLTAGE, CURRENT[], in cui storare i dati, e solo in una seconda parte stamparli, magari direttamente su excel o su matlab se riesco a trovare il modo di farlo, in maniera tale da poterli manipolare per grafici direttamente.
secondo voi riesco ad aumentare il numero di misure che riesco a prendere se li metto negli array invece che stamparli subito in output?
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 83
Posts: 8239
:(){:|:&};:
|
 |
« Reply #14 on: October 29, 2012, 11:02:25 am » |
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 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.
|
|
|
|
|
Logged
|
|
|
|
|
|