Go Down

Topic: Problemas de dessincronização de dados Arduino Xbee+Computador Xbee (Read 2925 times) previous topic - next topic

xaral

Olá pessoal!
Eu estou a desenvolver um projeto onde tenho de enviar dados de 30 em 30 segundos  de um Arduino ligado a um Xbee para um Xbee ligado à porta série do meu portátil. Por sua vez no portátil através de um programa feito no processing recebo os dados na porta série e coloco-os em gráfico. Acontece que após ter deixado o projeto rolar durante a noite ao analisar os dados recebidos no processing deu para ver que a sua qualidade não era a melhor, pois por vezes havia dessincronização dos dados recebidos pelo xbee ligado ao pc, como podem ver de seguida:

04-07-2012 19:51   0,321   73,9   51,8   0,033   1
04/07/152 00:�:48,6   0,033   4   7   12   19
04-07-2012 19:54   0,274   63,1   44,1   0,034   1
...
04/07/12 20,26:�:�   7   12   20   36   0
04-07-2012 20:36   NaN   48,1   0,065   NaN   7
04/07/12 230:00,265:60,066   NaN   7   12   20   38
04-07-2012 20:40   0,271   62,3   43,6   0,068   1

Segundo consigo perceber ele não obedece à sequência de valores que implementei, sendo que muitas das vezes salta.
Em relação ao problema ele só pode estar relacionado com o Xbee pois estou a usar um cartão sd no arduino para armazenar os dados recolhidos e neste caso está tudo bem...
Em relação à configuração dos Xbees estão usando ambos o modo AT, sendo um o router e outro o coordenador.
Em relação ao código não estou usando nada diretamente ligado ao xbee, pelo que apenas imprimo os valores na porta série do arduino/xbee e os recolho pela porta série do computador.
Acredito que no código vou ter de implementar outra estratégia ou utilizar o modo API, mas gostava que alguém me pudesse dar umas dicas, ou então dizer onde posso encontrar projetos semelhantes...

hugo007

Que baud rate estas a utilizar?
Tenta baixar o baud para os 9600 caso o tenhas mais elevado e por uma questao de teste coloca os perto um do outro.

Debian,Mint,Ubuntu
Arduino Mega 2560
Arduino Nano
Arduino Duemilanove
MAC OS Montain Lion
Raspberry PI Model B

xaral

Estou a usar ambas as condições...
Será que é por ter tantos dados? Estava a pensar utilizar o modo API ou então colocar um caracter diferente À frente de cada valor enviado, de forma a tentar solucionar o problema. Que achas?

bubulindo

Sem ver o código apenas podemos comentar que há algo estranho na ligação das XBee.

Como escrever no cartão provavelmente é feito numa chamada bloqueante, é provável que esses dados estejam sempre correctos. Escrever na porta série, não é bloqueante e pode haver alguma coisa no teu programa que bloqueie a porta série (é difícil, mas nunca se sabe) ou o que é mais provável, que o buffer esteja a ser corrompido com dados a mais ou algo do género. Já experimentaste enviar menos dados à mesma frequência ou os mesmos dados a uma frequência menor?

Podes colocar aqui parte do código ou o código completo?

This... is a hobby.

xaral

Este é o código completo do Arduino que está a recolher os dados e a enviar posteriormente para o Xbee ligado ao meu computador, onde o processing recolhe os mesmos dados e os reproduz em gráficos...

Code: [Select]
#include <Wire.h>  //I2C library
#include <SD.h>    //SD library
#define DS1307_ADDRESS 0x68 //RTC library

byte zero = 0x00; //workaround for issue #527 (RTC variable)

//definition of pin on Arduino board
const int PIR1 = 2;
const int PIR2 = 3;
const int LED = 5;
const int pinPot = A0;
const int CS_pin = 4;  
const int pow_pin = 8;

//Motion Detection Variables
int val1 = 0;             //PIR1 value
int val2 = 0;             //PIR2 value
int reading = 0;          //US value
int oldreading = 0;       //oldUS value
int count = 0;            //counter to keep LED tu
int calibrationPIR = 0;  //calibration time of PIR sensors
int presence_state = 0; //sets initial value of presence as 0, without presence




const int numberOfSamples = 1185;  

//Callibration Constants
const int Vrms = 230;
const float PF = 0.70;//set an average Power Factor value

//CR Magnetics CR31000-3000 CT parameters
const float CT_BURDEN_RESISTOR  = 180;
const float CT_TURNS     = 3000;

/*YHDC SCT-013-030 CT parameters
const float CT_BURDEN_RESISTOR  = 62;
const float CT_TURNS            = 1800;*/

//Calibration coeficients
int calibrationCT = 0;  //calibration time of PIR sensors
const float ICAL = 0.96;
int lastSampleI,sampleI; //Sample variables
float lastFilteredI, filteredI; //Filter variables
float sqI, sumI;  //Power calculation variables
float Irms; //Useful value variables
float apparentPower,realPower;
float kilowattHour;

unsigned long last_kwhTime;
unsigned long kwhTime;  

//Real Time Clock Variables
int second, minute, hour, weekDay, day, month,year;
 
void setup()
{
 Wire.begin();          // start the I2C bus

 Serial.begin(9600);    // open the serial port:
 
 //Definition of input/output values
 pinMode(PIR1,INPUT);
 pinMode(PIR2,INPUT);
 pinMode(LED,OUTPUT);
 pinMode(pinPot,INPUT);
 pinMode(CS_pin, OUTPUT);
 pinMode(pow_pin, OUTPUT);
 
 digitalWrite(pow_pin, HIGH);  

 //Initialize Card
 if (!SD.begin(CS_pin))
 {
     Serial.println("Card Failure");
     return;
 }
 //Serial.println("Card Ready");
 
 //Read the Configuration information (COMMANDS.txt)
 File logFile = SD.open("SMEP_SD.csv", FILE_WRITE);
 if (logFile)
 {
   String header = "day-month-year hour:minute:second;Irms (A);Apparent Power (W);Real Power (W);Energy (kWh);Presence";
   logFile.println(header);
   logFile.close();
   Serial.println(header);    
 }
 else
 {
   Serial.println("Could not read command file.");
   return;
 }  
}

void loop()
{
 runRTC();  
 passiveIR();
 ultrasonic();  
 presence();

 if(second == 0  || second == 30 ){ //condition to run functions  
                                        //only from 30 to 30 seconds  
   printDate();
   consumption();

  if( calibrationPIR < 1 ){

   presence_state=0;
   calibrationPIR++;
  }  
   Serial.println(presence_state);
   
   File logFile = SD.open("SMEP_SD.csv" , FILE_WRITE);
   if (logFile)
   {//print to micro SD card
   logFile.print(day);
   logFile.print("/");      
   logFile.print(month);
   logFile.print("/");    
   logFile.print(year);
   logFile.print(" ");
   logFile.print(hour);
   logFile.print(":");
   logFile.print(minute);
   logFile.print(":");
   logFile.print(second);
   logFile.print(";");    
   logFile.print(Irms,3);
   logFile.print(";");
   logFile.print(apparentPower,1);
   logFile.print(";");
   logFile.print(realPower,1);
   logFile.print(";");
   logFile.print(kilowattHour,3);
   logFile.print(";");
   logFile.println(presence_state);

   logFile.close();
   }

   else
   {
     Serial.println("Couldn´t open log file");
   }
   presence_state=0;    
 }
 delay (500);  //set a delay to avoid the print on serail port of two lines of values
}

void passiveIR()
{    
 val1 = digitalRead(PIR1);
 val2 = digitalRead(PIR2);
 delay (200);
}

void ultrasonic()
{
 // step 1: instruct sensor to read centimeters
 Wire.beginTransmission(112);
                             
                             
 Wire.write(byte(0x00));      
 Wire.write(byte(0x51));    
                             
 Wire.endTransmission();      // stop transmitting

 // step 2: wait for readings to happen
 delay(70);                   // datasheet suggests at least 65 milliseconds

 // step 3: instruct sensor to return a particular echo reading
 Wire.beginTransmission(112); // transmit to device #112
 Wire.write(byte(0x02));      // sets register pointer to echo #1 register (0x02)
 Wire.endTransmission();      // stop transmitting

 // step 4: request reading from sensor
 Wire.requestFrom(112, 2);    // request 2 bytes from slave device #112

 // step 5: receive reading from sensor
 if(2 <= Wire.available())    // if two bytes were received
 {
   oldreading = reading;
   reading = Wire.read();    // receive high byte (overwrites previous reading)
   reading = reading << 8;   // shift high byte to be high 8 bits
   reading |= Wire.read();   // receive low byte as lower 8 bits
 }

 delay(25);                 // wait before next reading:
}

void presence()
{  
//the follow condition memorizes if there was a motion during the 30seconds and print it
int f = reading - oldreading;

 if((val1 == LOW) || (val2 == LOW) || (f > 15)){
   presence_state=1;    
   digitalWrite(LED,HIGH);
 }
 
 else{
   digitalWrite(LED,LOW);
 }    
}
 
void consumption()
{  

 for (int n=0; n < numberOfSamples; n++)
 {    

   lastSampleI = sampleI;     //Used for current offset removal
   
   lastFilteredI = filteredI; //Used for voltage offset removal
   
   //sampleI = map(analogRead(pinPot),0,1023,0,30);    
    sampleI = analogRead(pinPot);  
   
   //Apply digital high pass filters to remove 2.5V DC offset (centered on 0V)    
   filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);
     
 
  //Root-mean-square method current
   //1) square current values
   sqI = filteredI * filteredI;
   //2) sum
   sumI += sqI;
 }
   
 //Calculation of the root of the mean of the current squared (rms)
 //Calibration coeficients applied.  
 //Calculated ratio constants
 ///I_Ratio=(CT_Turns / CT_BR)* (5V/1024)*ICA
 float I_RATIO = CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL;  
 Irms = I_RATIO*sqrt(sumI / numberOfSamples);
 
 //condition to avoid when there's no current the code
 //prints a current value due to resolution of ADC
 
 if(Irms <0.3 || calibrationCT < 1 ){
 Irms=0.000;    
 Serial.print(Irms,3);
 Serial.print(';');

 // Calculate power values
 apparentPower = Vrms * Irms;
 realPower = PF * apparentPower;
 
 Serial.print(apparentPower,1);
 Serial.print(';');
 Serial.print(realPower,1);
 Serial.print(';');  
 
 // Calculate running total kilowatt hours
 // This value will reset in 50 days  
 last_kwhTime = kwhTime;
 kwhTime = millis();
 kilowattHour += (realPower / 1000) * ((kwhTime - last_kwhTime) / 3600000.0);
 Serial.print(kilowattHour,3);
 Serial.print(';');  
 // Reset sample totals
 sumI = 0;
 calibrationCT++;
 }
 else{
 //if(Irms >= 0.14 && calibrationCT >= 1 ){

 Serial.print(Irms,3);
 Serial.print(';');

 // Calculate power values
 apparentPower = Vrms * Irms;
 realPower = PF * apparentPower;
 
 Serial.print(apparentPower,1);
 Serial.print(';');
 Serial.print(realPower,1);
 Serial.print(';');  
 
 // Calculate running total kilowatt hours
 // This value will reset in 50 days  
 last_kwhTime = kwhTime;
 kwhTime = millis();
 kilowattHour += (realPower / 1000) * ((kwhTime - last_kwhTime) / 3600000.0);
 Serial.print(kilowattHour,3);
 Serial.print(';');  
 // Reset sample totals
 sumI = 0;
 calibrationCT++;
 }
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
 return ( (val/16*10) + (val%16) );
}

void runRTC(){

 // Reset the register pointer
 Wire.beginTransmission(DS1307_ADDRESS);
 Wire.write(zero);
 Wire.endTransmission();

 Wire.requestFrom(DS1307_ADDRESS, 7);

 second = bcdToDec(Wire.read());
 minute = bcdToDec(Wire.read());
 hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
 weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
 day = bcdToDec(Wire.read());
 month = bcdToDec(Wire.read());
 year = bcdToDec(Wire.read());
 }
 

void printDate(){

 Serial.print(day);
 Serial.print(";");
 Serial.print(month);
 Serial.print(";");
 Serial.print(year);  
 Serial.print(";");
 Serial.print(hour);
 Serial.print(";");
 Serial.print(minute);
 Serial.print(";");
 Serial.print(second);
 Serial.print(";");

}



xaral

Em relação ao processing estou napplets, mas aqui fica a parte principal do código onde são tratados os dados recebido na porta série a partir do xbee

Code: [Select]
import napplet.*;
import processing.serial.*;
Serial port;

PrintWriter dadosSMEP;

int count;
//variables to receive on serial port
float yeartime, monthtime, daytime;
float hourtime, minutetime, secondtime, oldsecondtime ;
float presvalue, oldpresvalue;
float Irms;
float apparentPower,realPower;
float kilowattHour;
float timeX;  //Calculates the total time, using the time function of processing necessary to use on graphs Xaxis

//Size of the window
int plotX=1150, plotY=800;
//Dimension of each graph window
int plotgwX=575, plotgwY=312;
//plotmw means the height of the main window
int plotmwY=176;

//
color bgc=color(0, 153, 0); //backgroung color of each window
color graphc=color(#4D4D4A);//graph line color
color textc=color(255);     //text color on graph label

PFont plotFont; //font used in each graph

void setup() {

 
  size(plotX,plotY);
 
  // Print a list of the serial ports, for debugging purposes:
  println(Serial.list());

  // Open whatever port is the one you're using.
  port = new Serial(this,"COM14", 9600);
  // don't generate a serialEvent() unless you get a newline character:
  port.bufferUntil('\n');
 
  NAppletManager nappletManager = new NAppletManager(this);

  //define the initial points of each window created in our sketch
  nappletManager.createNApplet("Irms", 0, 0);
  nappletManager.createNApplet("RealPower", width/2, 0);
  nappletManager.createNApplet("kWh", 0, plotgwY); 
  nappletManager.createNApplet("Presence", width/2, plotgwY);
  nappletManager.createNApplet("MainWindow", 0, height-plotmwY);

  plotFont = createFont("SansSerif", 20);
  textFont(plotFont);
 
  //setup the text file to be created with descrition of several parameters
  dadosSMEP = createWriter("dadosSMEP.csv");
  dadosSMEP.print("Date");
  dadosSMEP.print(";");     
  dadosSMEP.print("Irms"); 
  dadosSMEP.print(";"); 
  dadosSMEP.print("Apparent_Power"); 
  dadosSMEP.print(";"); 
  dadosSMEP.print("Real_Power"); 
  dadosSMEP.print(";");
  dadosSMEP.print("kWh"); 
  dadosSMEP.print(";");
  dadosSMEP.println("Presence");
 
}


void draw() {
  background(0, 153, 0);
  timeX=60.0*minutetime+secondtime+hourtime*3600.0; //Calculates the total time, using the time function of processing 
                                              //necessary to use on graphs Xaxis   

  //convert the float number to integer
  String intyeartime = nf(yeartime, 2,0);
  String intmonthtime = nf(monthtime, 2,0);
  String intdaytime = nf(daytime, 2,0);
  String inthourtime = nf(hourtime, 2,0);
  String intminutetime = nf(minutetime, 2,0);
  String intsecondtime = nf(secondtime, 2,0);


  if(secondtime != oldsecondtime){//just print if the time change using second from Arduino Time
   
  //print the data received from Arduino on the text file
  dadosSMEP.print(intyeartime+"/"+intmonthtime+"/"+intdaytime+" "+inthourtime+":"+intminutetime+":"+intsecondtime);
  dadosSMEP.print(";");   
  dadosSMEP.print(Irms);
  dadosSMEP.print(";"); 
  dadosSMEP.print(apparentPower);
  dadosSMEP.print(";");
  dadosSMEP.print(realPower);
  dadosSMEP.print(";");
  dadosSMEP.print(kilowattHour);
  dadosSMEP.print(";"); 
  dadosSMEP.println(presvalue);
 
  dadosSMEP.flush();
  }
  oldsecondtime = secondtime;
}

void mousePressed()
{
  println("Coordinates: " + mouseX +"," + mouseY);
}

void serialEvent(Serial port)
{
  String input = port.readStringUntil('\n');//le o que chega a porta ate ao enter para importar as variaveis do arduino   

  /*para isto e necessario que no sketch do arduino as variaveis sejam imprimidas com Serial.print(variavel)
  e seguidas de virgula ou seja outro Serial.print(",").Sendo que a ultima variavel a registar e imprimida com
  Serial.println(variavel) */
                                                                                     
  if (input != null)//se a string contiver algo
  {
    input = trim(input); // limpa a string de espaços vazios que não sejam necessários
    // The data is split into an array of Strings with a comma or asterisk as a delimiter and converted into an array of integers.
    float [] infos =float (split(input, ";")); //preenche uma matriz com as variaveis importadas sendo que as diferentes variaveis vao para locais diferentes da matriz infos [0],infos [1]...

    if (infos.length >=11) //11 e o numero de variaveis que importo do arduino "ainda nao percebi bem porque e' necessario este if"
    {
      daytime = infos [0];
      monthtime = infos [1];     
      yeartime = infos [2];
      hourtime = infos [3];
      minutetime = infos [4];
      secondtime = infos [5];
      Irms = infos [6];
      apparentPower = infos [7];
      realPower = infos [8];
      kilowattHour = infos [9];
      presvalue = infos [10]; //presence value
    }
  }
}


Espero que possa ajudar e desculpa a possível estrutura do código mas foi o meu primeiro projeto nesta área :)

Go Up