Demo entry 6640645

Arduino ACK

   

Submitted by anonymous on Sep 12, 2017 at 15:25
Language: Arduino. Code size: 25.1 kB.

#include <XBee.h>
#include <SPI.h>
#include <SD.h>


#define MAX_NODES 3     // Numero max di nodi sensori che possono essere presenti nella rete

    int nodeCount = 0; 
    int a=0;
    int h=1;
    byte addr[2];
    int indirizzo=1;
    byte sinc[1]={'s'};


// conversione intero in due byte
union ArrayToInteger {
 uint32_t integer;
 byte conversione[4];
};


byte inputStream[4];
uint32_t longPackets;


XBee xbee = XBee();
AtCommandRequest request = AtCommandRequest();
AtCommandResponse response = AtCommandResponse();

Tx16Request scelta, txData, tx, txMessaggio;
TxStatusResponse txStatus = TxStatusResponse();
Rx16Response rx16 = Rx16Response();
Rx16Response rxFile = Rx16Response();
uint16_t senderShortAddress;

uint8_t ND[] = {'N','D'};         // Node Discover Command
int timeout = 10000;              // Node Discover Time
byte addressList[MAX_NODES*2];    // Lista con tutti gli indirizzi dei nodi attivi nella rete (l'indirizzo di un singolo nodo occupa 2 byte)


////////////////////////////////////////////////////////////////////////////////////
// Crea il nome del File txt dinamicamente (Data00 - Data 99)
////////////////////////////////////////////////////////////////////////////////////
#define FILE_BASE_NAME "Data"
const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[] = FILE_BASE_NAME "00.txt";

char file_Binario[]="binary.bin";  // Nome file binario

File file, filebin, myFile;

byte fsAcc=0;               //Sampling frequency
byte gForce=0;              //G - Force
uint8_t freqAxdl[3];
byte longPacketsHigh;       // numero di pacchetti binari da ricevere (MSB)
byte longPacketsLow;        // numero di pacchetti binari da ricevere (LSB)
byte smallPackets;          // dimensione dell'ultimo pacchetto dati da ricevere 
byte interruptFIFO;         // numero di letture dalla FIFO tramite interupt

// Variabili utilizzate per convertire dati binari in ASCII
int8_t first;   
int16_t Xd=0;   

boolean rispostaFirstMsg, rispostaMsg, sentMsg;
boolean consegnato;
boolean fileConversion;

char c; //to start loop switch-case

uint8_t dataLength;
uint8_t data=0;

const uint8_t CS_PIN = 10;    //pin CS

int ledPin =  13;             // Pin diagnostico (sul teensy)

////////////////////////////////////////////////////////////////////////////////////
// Scopre i nodi attivi nella rete
////////////////////////////////////////////////////////////////////////////////////
void networkDiscoveryNodes(){
  
  request.clearCommandValue();
  int h=0;
  Serial.println("=== Node Discovery ===");
  
  request.setCommand(ND);
  Serial.println(" Sending command Node Discovery Command to the XBee. ");
  Serial.println(" Scan in corso dei nodi attivi della rete ...." );
  xbee.send(request);
  while(xbee.readPacket(timeout)) {
  
    // should be receiving AT command responses
    if (xbee.getResponse().getApiId() == AT_COMMAND_RESPONSE) {
      xbee.getResponse().getAtCommandResponse(response);
      if (response.isOk()) {
          if (response.getValueLength() > 0) {

          byte risposta[response.getValueLength()];
          Serial.print("Node discovered !  Full Address --> ");
          for (int i = 0; i < response.getValueLength(); i++) {
            risposta[i]=(response.getValue()[i]);
            Serial.print(risposta[i], HEX);
            Serial.print(" ");
          }
          
          nodeCount++;
          for(int a=0; a<2; a++){
            addressList[h]=risposta[a];
            h++;
          }
          
          Serial.println(" ");
          Serial.print("Indirizzo 16 bit : ");
          Serial.print(risposta[0], HEX);
          Serial.print(risposta[1], HEX);
          Serial.println("");
      }
    }
  }
  
 
  }
  Serial.print("Results: ");
  Serial.print(nodeCount, DEC);
  Serial.println(" node(s) responded.");
  Serial.println("");  
}

////////////////////////////////////////////////////////////////////////////////////
// funzione blink led
////////////////////////////////////////////////////////////////////////////////////
void iLed(int pin, int times, int wait) {
    
    for (int i = 0; i < times; i++) {
      digitalWrite(pin, HIGH);
      delay(wait);
      digitalWrite(pin, LOW);
      delay(wait);
      }
}

////////////////////////////////////////////////////////////////////////////////////
// convert FIFO sample to unsigned int
////////////////////////////////////////////////////////////////////////////////////
int16_t convertFIFOdata(uint8_t hiByte, uint8_t loByte)
{ int16_t x=0;
    //mask off id bits, combine low byte
    x = ((hiByte & 0x3F) << 8) | loByte;
    // get sign bits, copy into B15, B14, combine
    x = ((x & 0x3000) << 2) | x;
    return(x);
}

////////////////////////////////////////////////////////////////////////////////////////
// Converte file bin in file ASCII (.txt)
////////////////////////////////////////////////////////////////////////////////////////
boolean convertBinaryFile(){
    
    // read from the file until there's nothing else in it:
    int x=0;
    fileConversion=false;
    Serial.println("Converto il file bin in file ASCII ");

    while (SD.exists(fileName)) {
      if (fileName[BASE_NAME_SIZE + 1] != '9') {
        fileName[BASE_NAME_SIZE + 1]++;
      } else if (fileName[BASE_NAME_SIZE] != '9') {
        fileName[BASE_NAME_SIZE + 1] = '0';
        fileName[BASE_NAME_SIZE]++;
      } else {
        
        Serial.println(F("Can't create file name"));
        return;
    }
  }
        //file = SD.open("conv.txt", FILE_WRITE);
        file = SD.open(fileName, FILE_WRITE);
        if (!file) {
          Serial.println(F("open failed"));
          return;
        }
        Serial.print(F("opened: "));
        Serial.println(fileName);

        
    filebin=SD.open(file_Binario, FILE_READ);

    // Prima riga del file .txt -> indirizzo del nodo sensore che ha inviato i dati
    file.print("Indirizzo nodo sensore : " );
    file.println(senderShortAddress,HEX) ;

    
    byte paks1=filebin.read();
    byte paks2=filebin.read();
    byte paks3=filebin.read();
    byte paks4=filebin.read();
    
    // Seconda riga del file .txt -> letture dalla FIFO tramite interrupt   
    byte fifoInterrupts=filebin.read();
    file.print("Letture dalla FIFO :" );
    file.println(fifoInterrupts);

    // Terza riga del file .txt -> Frequenza di campionamento utilizzata
    byte freqCampionamento=filebin.read();
    file.print("Frequenza di campionamento : ");
    switch(freqCampionamento){
      case 1: file.println("12.5 Hz");  break;
      case 2: file.println("25 Hz");    break;  
      case 3: file.println("50 Hz");    break;
      case 4: file.println("100 Hz");   break;
      case 5: file.println("200 Hz");   break;
      case 6: file.println("500 Hz");   break;
    }

    // Quarta riga del file .txt -> Lunghezza (byte) dell'ultimo pacchetto ricevuto
    byte pacchettoCorto=filebin.read();
    file.print("Lunghezza ultimo pacchetto: ");
    file.println(pacchettoCorto);
    //file.println(' ');


    // Conversione dati binari della FIFO in ASCII ( n campione - asse x - asse y - asse z)
    while(filebin.available()) {
        file.print(x);
        file.print(' ');
        first=filebin.read();
        Xd = convertFIFOdata(filebin.read(),first);
        file.print(Xd);
        file.print(' ');
        first=filebin.read();
        Xd = convertFIFOdata(filebin.read(),first);
        file.print(Xd);
        file.print(' ');
        first=filebin.read();
        Xd = convertFIFOdata(filebin.read(),first);
        file.print(Xd);
        file.println(' ');
        //file.print('\n');
        x++;
    }
    Serial.print("Bin file converted to ASCII. ");
    Serial.print("Number of lines (lines divided by fs is about the total time): ");
    Serial.print(x);
    Serial.print("\n ");
    Serial.println("---------------------------------------------");
    
    filebin.close();
    file.close();
    
    fileConversion=true;
    return fileConversion;
}

//////////////////////////////////////////////////////////////////////////////////////
// Read Sinc Response from end node 
////////////////////////////////////////////////////////////////////////////////////
 boolean readSincMsg(Rx16Response rr16) {
    
   boolean rispostaMsg=false;
     
    xbee.readPacket();
      if (xbee.getResponse().isAvailable()) {
        //Serial.println("got response");
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE || xbee.getResponse().getApiId() == RX_64_RESPONSE) {
        //Serial.println("got a Rx packet");        
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
                xbee.getResponse().getRx16Response(rr16);
                rispostaMsg=true;
                dataLength=rr16.getDataLength();
                byte byteArray[rr16.getDataLength()];
                for (int i = 0; i < rr16.getDataLength(); i++) { 
                    byteArray[i]=rr16.getData(i);
                    }
                   
                 }         
        }
      }
      return rispostaMsg;
      }
	  
//////////////////////////////////////////////////////////////////////////////////////
// Read message from Xbee 
////////////////////////////////////////////////////////////////////////////////////
 boolean readMsg(Rx16Response rr16) {
    
   boolean rispostaMsg=false;
     
    xbee.readPacket();
      if (xbee.getResponse().isAvailable()) {
        //Serial.println("got response");
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE || xbee.getResponse().getApiId() == RX_64_RESPONSE) {
        //Serial.println("got a Rx packet");        
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
                xbee.getResponse().getRx16Response(rr16);
                rispostaMsg=true;
/*                Per ricavare l''indirizzo 64 bit
//                XBeeAddress64 senderLongAddress = rx64.getRemoteAddress64();
//                senderLongAddress = rx64.getRemoteAddress64();
//                Serial.print(senderLongAddress.getMsb(),HEX);
//                Serial.println(senderLongAddress.getLsb(),HEX);*/

                //Get the 16bit address of source node from incoming packet.
                Serial.print("Source Node short address:0x");
                senderShortAddress = rr16.getRemoteAddress16();
                Serial.println(senderShortAddress,HEX) ;
                                
                dataLength=rr16.getDataLength();
                Serial.print("Lunghezza pacchetto: ");
                Serial.println(dataLength);
                Serial.print("Contenuto pacchetto: ");
                byte byteArray[rr16.getDataLength()];
                for (int i = 0; i < rr16.getDataLength(); i++) { 
                    byteArray[i]=rr16.getData(i);
                    Serial.print(byteArray[i]);
                    }
                   
                 // Print the RSSI value of the received packet
                 //option=rx16.getRssi();
                 //Serial.println(option);
              }         
        }
      }
      return rispostaMsg;
      }

//////////////////////////////////////////////////////////////////////////////////////
// Riceve il file Binario (calcola il numero di pacchetti totali da ricevere)
////////////////////////////////////////////////////////////////////////////////////
 boolean receiveBinaryFile(Rx16Response rr16) {
  
   boolean rispostaFirstMsg=false;
      xbee.readPacket();
      if (xbee.getResponse().isAvailable()) {
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE || xbee.getResponse().getApiId() == RX_64_RESPONSE) {  
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
                xbee.getResponse().getRx16Response(rr16);
                
                rispostaFirstMsg=true;
                
                senderShortAddress = rr16.getRemoteAddress16();                               
                dataLength=rr16.getDataLength();
                byte byteArray[rr16.getDataLength()];
                for (int i = 0; i < rr16.getDataLength(); i++) { 
                    byteArray[i]=rr16.getData(i);              
                }
                  // I Primi quattro byte del primo pacchetto ricevuto danno informazioni su quanti pacchetti ricevere
                  for(int i=0; i<sizeof(inputStream); i++){
                     inputStream[i]=byteArray[i];
                    }

                // Converte i quttro byte in un Intero (long integer)
                ArrayToInteger converter; 
                for(int i=0; i < sizeof(inputStream); i++){
                    converter.conversione[i]=inputStream[i];
                }
                
                  longPackets=converter.integer;
               
                  Serial.print("Pacchetti completi : ");
                  Serial.println(longPackets);
                  Serial.print("Letture dalal FIFO: ");
                  interruptFIFO= byteArray[4];
                  Serial.print(smallPackets);
                  Serial.print("Frequenza di campionamento : ");
                  fsAcc=byteArray[5];   
                  Serial.println(fsAcc);
                  Serial.print("Lunghezza ultimo pacchetto : ");
                  smallPackets=byteArray[6];   
                  Serial.println();

         //Crea un nuovo file binario (se già esiste cancella il precedente)
         if(SD.exists(file_Binario)){
            SD.remove(file_Binario);}

          
          filebin=SD.open(file_Binario, FILE_WRITE);
          for (int i = 0; i < rr16.getDataLength(); i++){
          filebin.write(byteArray[i]);
          }


          for(int h=1;h<longPackets; h++){
          while(!readBinaryMsg(rx16, filebin));
          Serial.print(h);
          }
       
            if(smallPackets!=0){
          while(!readBinaryMsg(rx16, filebin));
        }        
    }        
   }
 }    
      filebin.close();    
      return rispostaFirstMsg;
}


//////////////////////////////////////////////////////////////////////////////////////
// Riceve un pacchetto binario 
////////////////////////////////////////////////////////////////////////////////////
 boolean readBinaryMsg(Rx16Response rr16, File filebin) {

   boolean rispostaMsg=false;
   
    xbee.readPacket();
      if (xbee.getResponse().isAvailable()) {
        //Serial.println("got response");
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE || xbee.getResponse().getApiId() == RX_64_RESPONSE) {
        //Serial.println("got a Rx packet");        
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
                xbee.getResponse().getRx16Response(rr16);
                rispostaMsg=true;
/*                Per ricavare l''indirizzo 64 bit
//                XBeeAddress64 senderLongAddress = rx64.getRemoteAddress64();
//                senderLongAddress = rx64.getRemoteAddress64();
//                Serial.print(senderLongAddress.getMsb(),HEX);
//                Serial.println(senderLongAddress.getLsb(),HEX);*/

                //Get the 16bit address of source node from incoming packet.
                //Serial.print("Source Node short address:0x");
                //senderShortAddress = rr16.getRemoteAddress16();
                //Serial.println(senderShortAddress,HEX) ;
                                
                dataLength=rr16.getDataLength();
                Serial.print("Lunghezza pacchetto: ");
                Serial.println(dataLength);
                //Serial.print("Contenuto pacchetto: ");
                byte byteArray[rr16.getDataLength()];
                for (int i = 0; i < rr16.getDataLength(); i++) { 
                    byteArray[i]=rr16.getData(i);
                    filebin.write(byteArray[i]);                 
                 // Print the RSSI value of the received packet
                 //option=rx16.getRssi();
                 //Serial.println(option);
              }         
        }
        
      }
      
      return rispostaMsg;
      }
 }

////////////////////////////////////////////////////////////////////////////////////
// Invia un messaggio 
////////////////////////////////////////////////////////////////////////////////////
boolean sendMsg(Tx16Request msg){
 
      boolean sentMsg=false;
      xbee.send(msg);
      if (xbee.readPacket(10000)) {
        // got a response!

        // should be a znet tx status                   
        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {
           xbee.getResponse().getTxStatusResponse(txStatus);
                
           // get the delivery status, the fifth byte
           if (txStatus.getStatus() == SUCCESS) {
                Serial.println(" --- CONSEGNATO! --- ");// success.  time to celebrate
//                flashLed(statusLed, 1, 50);
                sentMsg=true;
           } else {
                Serial.println("remote Xbee did not receive our packet"); // the remote XBee did not receive our packet. is it powered on?
              //  flashLed(errorLed, 2, 500);
           }
        }      
    } else if (xbee.getResponse().isError()) {
      Serial.print("Error reading packet.  Error code: ");  
      Serial.println(xbee.getResponse().getErrorCode());
    } else {
     Serial.println(" local XBee did not provide a timely TX Status Response.  Radio is not configured properly or connected");
    }
    return sentMsg;
  }


////////////////////////////////////////////////////////////////////////////////////
// Invia il messaggio di sincronizzazione
////////////////////////////////////////////////////////////////////////////////////
boolean sendSyncMsg(Tx16Request msg){
 
      boolean sentMsg=false;
      xbee.send(msg);
      if (xbee.readPacket(5000)) {               
        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {
           xbee.getResponse().getTxStatusResponse(txStatus);
                
           // get the delivery status, the fifth byte
           if (txStatus.getStatus() == SUCCESS) {
                Serial.println(" --- Messaggio di Sync CONSEGNATO! --- ");// success.  time to celebrate
//                flashLed(statusLed, 1, 50);
                sentMsg=true;
           } else {
                Serial.println("remote Xbee did not receive our packet"); // the remote XBee did not receive our packet. is it powered on?
              //  flashLed(errorLed, 2, 500);
           }
        }      
    } else if (xbee.getResponse().isError()) {
      Serial.print("Error reading packet.  Error code: ");  
      Serial.println(xbee.getResponse().getErrorCode());
    } else {
     Serial.println(" local XBee did not provide a timely TX Status Response.  Radio is not configured properly or connected");
    }
    return sentMsg;
  }

///////////////////////////////////////////////////////////////////////////////////////////////////
// Sincronizza i nodi della rete (invia il messaggio di sincronizzazione a ciascun nodo della rete)
///////////////////////////////////////////////////////////////////////////////////////////////////
void syncNetwork(){
          
          Serial.println("Sincronizzo i nodi della rete");
          
        // Sincronizzo i nodi della rete inviando un messaggio Unicast ad ogni singolo nodo
        // nell'ordine con cui sono stati scoperti dal comando NODE DISCOVER   
          
          while(h<=MAX_NODES && indirizzo!=0){          
          addr[0]=addressList[a];
          addr[1]=addressList[a+1];
          a++;
          a++;
          Serial.println("Sinc network while");
          indirizzo = addr[0] * 256 + addr[1];  //conversione 2 byte in uint16 per indirizzo nodo sensore
          
          if(indirizzo!=0){
             Serial.print(" --- Sincronizzo il nodo n: ");
             Serial.print(h);
             tx=Tx16Request(indirizzo, sinc, sizeof(sinc));  
             delay(50);
             while(!sendMsg(tx)); 
			 
			 
			 Rx16Response sincResponse;
       while(!readSincMsg(sincResponse));
			 Serial.println(" --> OK");           // Nodo sincronizzato
             h++;
            addr[0]=0;  
            addr[1]=0;
          
          }
  }
  Serial.println(" _____ NODI SINCRONIZZATI____");
  a=0;
  h=1;
  indirizzo=1;
}

////////////////////////////////////////////////////////////////////////////////////
// SETUP
////////////////////////////////////////////////////////////////////////////////////
void setup() {

  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  Serial3.begin(9600);
  xbee.setSerial(Serial3);
  delay(1000);  
  Serial.println("Premi un tasto per iniziare...");
  while (Serial.read() <= 0) {}

  while (!SD.begin(4)) {  Serial.println("initialization failed!");}
  Serial.println("initialization done.");

  // scoperta dei nodi attivi nella rete
  networkDiscoveryNodes();
  delay(500);
}

////////////////////////////////////////////////////////////////////////////////////
// LOOP
////////////////////////////////////////////////////////////////////////////////////
void loop() {
    
    Serial.println("Arduino Coordinator Node  (2017)");
    Serial.println(' ');
      
    Serial.println("______________________________");
  
    Serial.println(" Digita la tua scelta :");
    Serial.println(" Y - Ricevi il file");
    Serial.println(" i - Inizia la misura");
    Serial.println(" f - Termina la misura");
    Serial.println(" a - Setta frequenza 12.5 Hz");
    Serial.println(" b - Setta frequenza 25 Hz");
    Serial.println(" c - Setta frequenza 50 Hz");
    Serial.println(" d - Setta frequenza 100 Hz");
    Serial.println(' ');
    
    uint8_t answer[1]={0};
    c=-1;
    while(c<=0){
      c=Serial.read();
    }

    switch (c){
      case 'Y':
      case 'y':
        {
        answer[0]='y';
        //syncNetwork();    //provata con il nodo sensore provvisorio arduino (va tolta per il funzionamento con il teensy)
        Serial.println("Hai digitato il comando Y --> Ricevo file binari dai nodi attivi della rete ");

        // Invia il comando di "invio File" a ciascun nodo sensore della rete in modalità Unicast così da avere :
        // 1) Possibilità di leggere il bit di ACK (ed inviare di nuovo il comando se non èa ndato a buon fine)
        // 2) Evitare trasmissioni simultanee di più nodi sensori (un nodo aspetta che sia terminato un invio del nodo precedente per inviare a sua volta)
          while(h<=MAX_NODES && indirizzo!=0){    
          addr[0]=addressList[a];
          addr[1]=addressList[a+1];
          a++;
          a++;
          
          indirizzo = addr[0] * 256 + addr[1];  //conversione 2 byte in uint16 per indirizzo nodo sensore
          if(indirizzo!=0){

             Serial.print(" ---RICEVO FILE DAL NODO n: ");
             Serial.println(h);
          
          tx=Tx16Request(indirizzo, answer, sizeof(answer));  
          while(!sendMsg(tx)); 
          while(!receiveBinaryFile(rxFile));
          while(!convertBinaryFile());
          
          h++;
          
          addr[0]=0;  
          addr[1]=0;
          
          }
          
         else break;
          
       }
        Serial.println(" -------- File ricevuti ------------");   
        h=1;
        a=0;         
        indirizzo=1;
        break;
        }

      // Inizio MISURA
      case 'I':
      case 'i':
        {
        //syncNetwork();
        answer[0]='i';
        Serial.println("Hai digitato il comando i ");
        delay(200);
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }

       // Fine MISURA
      case 'F':
      case 'f':
        { 
        answer[0]='f';
        Serial.println("Hai digitato il comando f ");
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }

       
      case 'A':
      case 'a':
        {
        syncNetwork();
        answer[0]='a';
        Serial.println("Hai digitato il comando A ");
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }

      case 'B':
      case 'b':
        {
        syncNetwork();
        answer[0]='b';
        Serial.println("Hai digitato il comando B ");
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }

      case 'C':
      case 'c':
        {
        syncNetwork();
        answer[0]='c';
        Serial.println("Hai digitato il comando C ");
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }

      case 'D':
      case 'd':
        {
        syncNetwork();
        answer[0]='d';
        Serial.println("Hai digitato il comando D ");
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }

      case 'E':
      case 'e':
        {
        syncNetwork();
        answer[0]='e';
        Serial.println("Hai digitato il comando E ");
        tx=Tx16Request(0xFFFF, answer, sizeof(answer));
        while(!sendMsg(tx));
        break;
       }
       
      default:
      {
        Serial.println("Comando non valido");
        delay(1000);
      }
}

}

This snippet took 0.04 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).