Pages: [1]   Go Down
Author Topic: Problemas de dessincronização de dados Arduino Xbee+Computador Xbee  (Read 1096 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

Portugal
Offline Offline
Edison Member
*
Karma: 37
Posts: 1545
Pretending you know everything then you will learn nothing.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

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


Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3225
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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(";");

}


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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 smiley
Logged

Pages: [1]   Go Up
Jump to: