Xbee and xctu get data


9 posts
by makbut » Wed Aug 13, 2014 11:04 am
Hello, well it may be a litlle irrelevant but i don't know, maybe i should post it on general discussion(?)

I have an xbee on raspberry pi and another xbee in my laptop connected through usb.
On laptop the XCTU software is running and i use the terminal window to send commands and read what raspberry sends.
The thing is, raspberry sends a bunch of hexadecimals that i want to store somehow, but i cannot copy them from the xctu terminal.
Has anyone any idea how to do it?
Can i somehow by writing a programm watch the usb ,catch those data and do the rest that i want with them?
Posts: 25
Joined: Mon Nov 18, 2013 9:04 am
by danjperron » Wed Aug 13, 2014 1:59 pm
Hi makbut,


I did a lot of testing with the xbee and I use the xctu for configuration.

What is the xbee series you are using and in wich mode?


My laptop is a mac so I'm using 'screen' apllication to communicate via xbee to my rasberry pi.

On windows you will have to find yourself a terminal application since hyper terminal is not available anymore on win 7 & 8.

You could boot a linux version and use minicom or screen.

B.T.W. I don't know your skill but it is easy to write a visual basic or c++ to read the usb com port of xbee. Just figure out the COM number , from the device manager, and open it.

ex: in C++

Code: Select all
comhandle=CreateFile("\\\\.\\COM4",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
... use SetCommState() and SetCommTimeouts()  for baud rate, handshake and timings.


Use ReadFile(comhandle,....) to read the com
Use WriteFile(comhandle,...) to send



Daniel
Posts: 2617
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada
by makbut » Wed Aug 13, 2014 6:06 pm
Thank you very much for the answer.
I use xbee series 1 in transparent mode.
I will look more carefully your reply and try what you suggest.
I'll post as soon as I have a question or some progress.
Posts: 25
Joined: Mon Nov 18, 2013 9:04 am
by danjperron » Thu Aug 14, 2014 2:37 am
This is an example in c++ net using visual studio

On the Raspberry Pi , I made a small test program in python. The code will just send a number, which increments every second, to the TTL serial port where the Xbee is connected.


Code: Select all
pi@WebPi ~ $ cat xbeeCounter.py
#!/usr/bin/python
import serial
import time
ser = serial.Serial("/dev/ttyAMA0",baudrate=9600)
idx = 0
while True:
  ser.write(str(idx))
  ser.write("\r\n")
  time.sleep(1)
  idx = idx + 1



On the PC , I have another Xbee on an usb adapter.
I made a small program in visual studio, in c++ .net which will read the serial port and display the value on a form.

This is the file Form1.h

Code: Select all
#pragma once

namespace xbeeDisplay {

   using namespace System;
   using namespace System::ComponentModel;
   using namespace System::Collections;
   using namespace System::Windows::Forms;
   using namespace System::Data;
   using namespace System::Drawing;
   using namespace System::IO::Ports;
    using namespace System::Threading;

   /// <summary>
   /// Summary for Form1
   /// </summary>
   public ref class Form1 : public System::Windows::Forms::Form
   {
   private:
      static SerialPort^ _serialPort;
      Thread^ readThread; 

   public:
      Form1(void)
      {
         InitializeComponent();
         // serial port
         readThread = gcnew Thread(gcnew ThreadStart(this,&Form1::Read));

           // Create a new SerialPort object with default settings.
           _serialPort = gcnew SerialPort();

           // Allow the user to set the appropriate properties.
         _serialPort->PortName = "COM6";
           _serialPort->BaudRate = 9600;
        _serialPort->Open();
//_continue = true;
        readThread->Start();


         //
         //TODO: Add the constructor code here
         //
      }

   protected:
      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      ~Form1()
      {
         if (components)
         {
            delete components;
         }
      }
   private: System::Windows::Forms::Label^  label1;
   protected:

   private:
      /// <summary>
      /// Required designer variable.
      /// </summary>
      System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      void InitializeComponent(void)
      {
         this->label1 = (gcnew System::Windows::Forms::Label());
         this->SuspendLayout();
         //
         // label1
         //
         this->label1->AutoSize = true;
         this->label1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 48, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
            static_cast<System::Byte>(0)));
         this->label1->Location = System::Drawing::Point(26, 25);
         this->label1->Name = L"label1";
         this->label1->Size = System::Drawing::Size(68, 73);
         this->label1->TabIndex = 0;
         this->label1->Text = L"0";
         //
         // Form1
         //
         this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
         this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
         this->ClientSize = System::Drawing::Size(277, 129);
         this->Controls->Add(this->label1);
         this->Name = L"Form1";
         this->Text = L"Form1";
         this->ResumeLayout(false);
         this->PerformLayout();
      }
#pragma endregion

   
 delegate void SetTextDelegate(String^ text);

   void SetText(String^ text)
    {
      
        if (this->label1->InvokeRequired)
        {
            SetTextDelegate^ d = gcnew SetTextDelegate(this, &Form1::SetText);
            this->Invoke(d, gcnew array<Object^> { text });
        }
        else
        {
            this->label1->Text = text;
        }
    }

  void Read()
    {
     //   while (_continue)
       while(true)
      {
                String^ XbeeMessage = _serialPort->ReadLine();
            this->SetText(XbeeMessage->Trim('\n','\r'));  // use invoke method
        }
     }

   };
}




And this is the display output on my pc

XbeeCounter.jpg
Rpi Xbee to PC Xbee counter
XbeeCounter.jpg (10.91 KiB) Viewed 9244 times



I hope this will be helpfull


Daniel
Last edited by danjperron on Thu Aug 14, 2014 4:59 pm, edited 1 time in total.
Posts: 2617
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada
by danjperron » Thu Aug 14, 2014 4:52 pm
The previous code didn't store any data.

This is a modification of the code to capture each serial data to a file in MyDocument\XbeeCapture.txt


I add FormClosing function to terminate the thread and the serial port nicely.

B.T.W. I assume that you are sending a cariage return . If not! You will have to change the loop method in the Read Function.
- Do we have available Data.
No then wait a little. Use Thread::Sleep. You don't want the cpu constantly checking the serial port.
Yes then read all characters and append them to the file.


Code: Select all
#pragma once

namespace XbeeTest2 {

   using namespace System;
   using namespace System::IO;
   using namespace System::ComponentModel;
   using namespace System::Collections;
   using namespace System::Windows::Forms;
   using namespace System::Data;
   using namespace System::Drawing;
   using namespace System::IO::Ports;
    using namespace System::Threading;

   /// <summary>
   /// Summary for Form1
   /// </summary>
   public ref class Form1 : public System::Windows::Forms::Form
   {
   private:
      static SerialPort^ _serialPort;
      Thread^ readThread; 
     bool _continueSerial;

   public:
      Form1(void)
      {
         InitializeComponent();
         // serial port
         readThread = gcnew Thread(gcnew ThreadStart(this,&Form1::Read));

           // Create a new SerialPort object with default settings.
           _serialPort = gcnew SerialPort();

           // Allow the user to set the appropriate properties.
         _serialPort->PortName = "COM3";
           _serialPort->BaudRate = 9600;
        _serialPort->Open();
        _continueSerial = true;
        readThread->Start();


         //
         //TODO: Add the constructor code here
         //
      }

   protected:
      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      ~Form1()
      {
         if (components)
         {
            delete components;
         }
      }
   private: System::Windows::Forms::Label^  label1;
   protected:

   private:
      /// <summary>
      /// Required designer variable.
      /// </summary>
      System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      void InitializeComponent(void)
      {
        this->label1 = (gcnew System::Windows::Forms::Label());
        this->SuspendLayout();
        //
        // label1
        //
        this->label1->AutoSize = true;
        this->label1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 48, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
           static_cast<System::Byte>(0)));
        this->label1->Location = System::Drawing::Point(26, 25);
        this->label1->Name = L"label1";
        this->label1->Size = System::Drawing::Size(49, 73);
        this->label1->TabIndex = 0;
        this->label1->Text = L" ";
        //
        // Form1
        //
        this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
        this->ClientSize = System::Drawing::Size(277, 129);
        this->Controls->Add(this->label1);
        this->Name = L"Form1";
        this->Text = L"Form1";
        this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &Form1::Form1_FormClosing);
        this->ResumeLayout(false);
        this->PerformLayout();

     }
#pragma endregion

   
 delegate void SetTextDelegate(String^ text);

   void SetText(String^ text)
    {
     
        if (this->label1->InvokeRequired)
        {
            SetTextDelegate^ d = gcnew SetTextDelegate(this, &Form1::SetText);
            this->Invoke(d, gcnew array<Object^> { text });
        }
        else
        {
            this->label1->Text = text;
        }
    }

  void Read()
    {
     //   while (_continue)

      _serialPort->ReadTimeout=500;
       while(_continueSerial)
      {

             String^ XbeeMessage;
              try
            {
                   XbeeMessage = _serialPort->ReadLine();
            }
            catch (TimeoutException ^) {continue; }

            XbeeMessage = XbeeMessage->Trim('\n','\r');
            
            StreamWriter^ sw = File::AppendText(Environment::GetFolderPath(Environment::SpecialFolder::MyDocuments)+"\\XbeeCapture.txt");
            try
            {
               sw->WriteLine(XbeeMessage);
            }
            finally
            {
               if(sw)
                  delete (IDisposable^)sw;
            }

            this->SetText(XbeeMessage);  // use invoke method
        }
     }

   private: System::Void Form1_FormClosing(System::Object^  sender, System::Windows::Forms::FormClosingEventArgs^  e) {
            if(readThread)
            {
              _continueSerial=false;
              readThread->Join();   // wait until thread abort from it's loop
              delete readThread;
            }
               
            if(_serialPort)
            {
              _serialPort->Close();
              delete _serialPort;
            }
         }
};
}


Daniel
Posts: 2617
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada
by makbut » Thu Aug 14, 2014 7:11 pm
danjperron thank you very much for the posts, they were very helpful.

well, i don't know very well c++ and that thing with the gui seemed really complicated to me.
So i got the basic idea from what you wrote and i made a program which with success reads all the bytes that are sent from raspberry. I stored these bytes in a file which is also done with success.

Next i wanted to be able to run this programm on another computer too. I read somewhere that i should create a setup file, so i did the following:
Add new project.. -> Other Project Types->Setup and Deployment->Visual studio installer->setup wizard
and i created a setup file and then installed my programm on another computer too. The problem now is that the file with all those bytes that was successfully generated before, now it isn't. The whole rest program is executed successfully except for that..
Any idea?
Posts: 25
Joined: Mon Nov 18, 2013 9:04 am
by danjperron » Thu Aug 14, 2014 7:41 pm
Probably you try to wrote into the program file folder and when you install the software, everything get lock into read only or permission denied.

You should change the data folder to a writable location like MyDocuments (c:\users\the real user\Documents\your data folder) or the public document. There is a function to get the correct path.

b.t.w in which language did you program your code. VBA, c#, c++, MFC...

Daniel
Posts: 2617
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada
by makbut » Thu Aug 14, 2014 8:15 pm
c++.
ok, i will check it out later and post again :D
Posts: 25
Joined: Mon Nov 18, 2013 9:04 am
by alondra » Fri Jul 01, 2016 5:15 pm
was the xbee s1 or s2? was it in transparent or API mode?
Posts: 2
Joined: Thu Jun 30, 2016 6:43 pm