XBee Linux Serial Port on Raspberry Pi - linux

I have 2 Adafruit XBee 2 Modules each connected with 1 FTDI cable (ttyUSB0 and ttyUSB1)to the Raspberry Pi via a USB hub. I configure both XBee modules independently to be on the same PAN and then I try to read in a while loop with one, and write a simple message in a while loop in the other. For some reason I never read anything from the second port.
Here is the test code I am using.
Configure:
xbee::xbee(char* usbPort) {
/*
-> AT (check if xbee modem is responding)
<- OK
-> ATID (get current PAN)
<- 3332 (default, or something else)
-> ATID 3137 (set new id)
<- OK
-> ATID (check again)
<- 3137
-> ATWR (write the change to flash)
<- OK
*/
// Sleep for a little bit
QWaitCondition waitCondition;
QMutex mutex;
// Get a util object
Linuxutils util;
// Open a serial port
qDebug() << "Opening Serial Port:" << QString(usbPort);
char port[] = "ttyUSB1";
int fd = util.openSerialPort(port);
qDebug() << "Done opening Serial Port " << QString(usbPort) << ": " << fd;
int didConfigurePort = util.configureSerialPort(fd,9600);
qDebug() << "Did configure port successfully? " << didConfigurePort;
// Receive buffer
char rxBuffer[24];
/////////////////////////////////////////////////////////////////////////////
// Config Mode
memset(rxBuffer, 0, sizeof(rxBuffer));
char *msg = "+++";
qDebug() << "Writing config string to XBee ( +++ )";
util.writeToSerialPort(fd,msg);
qDebug() << "XBee written to, waiting for response of 'OK'";
while (true) {
int readNumberOfBytes = util.readFromSerialPort(fd,rxBuffer,4096);
printf("Received ( %d bytes ): %s\n", readNumberOfBytes,rxBuffer);
break;
}
/////////////////////////////////////////////////////////////////////////////
// AT (check if xbee modem is responding)
memset(rxBuffer, 0, sizeof(rxBuffer));
char *msg2 = "AT\n";
qDebug() << "Check if XBee is responding ( AT )";
util.writeToSerialPort(fd,msg2);
qDebug() << "XBee written to, waiting for response of 'OK'";
while (true) {
int readNumberOfBytes = util.readFromSerialPort(fd,rxBuffer,4096);
printf("Received ( %d bytes ): %s\n", readNumberOfBytes,rxBuffer);
break;
}
/////////////////////////////////////////////////////////////////////////////
// AT (get current PAN ID)
memset(rxBuffer, 0, sizeof(rxBuffer));
char *msg3 = "ATID\n";
qDebug() << "Get XBee PAN ID ( ATID )";
util.writeToSerialPort(fd,msg3);
qDebug() << "XBee written to, waiting for response which is integer of current PAN";
while (true) {
int readNumberOfBytes = util.readFromSerialPort(fd,rxBuffer,4096);
printf("Received ( %d bytes ): %s\n", readNumberOfBytes,rxBuffer);
break;
}
/////////////////////////////////////////////////////////////////////////////
// AT (get current PAN ID <VALUE>)
memset(rxBuffer, 0, sizeof(rxBuffer));
char *msg4 = "ATID 3137\n";
qDebug() << "Check if XBee is responding ( ATID 3137 )";
util.writeToSerialPort(fd,msg4);
qDebug() << "XBee written to, waiting for response after telling it to change to PAN 3137";
while (true) {
int readNumberOfBytes = util.readFromSerialPort(fd,rxBuffer,4096);
printf("Received ( %d bytes ): %s\n", readNumberOfBytes,rxBuffer);
break;
}
/////////////////////////////////////////////////////////////////////////////
// AT (get current PAN ID)
memset(rxBuffer, 0, sizeof(rxBuffer));
char *msg5 = "ATID\n";
qDebug() << "Get XBee PAN ID ( ATID )";
util.writeToSerialPort(fd,msg5);
qDebug() << "XBee written to, waiting for response which is integer of current PAN";
while (true) {
int readNumberOfBytes = util.readFromSerialPort(fd,rxBuffer,4096);
printf("Received ( %d bytes ): %s\n", readNumberOfBytes,rxBuffer);
break;
}
/////////////////////////////////////////////////////////////////////////////
// AT (get current PAN ID <VALUE>)
memset(rxBuffer, 0, sizeof(rxBuffer));
char *msg6 = "ATWR\n";
qDebug() << "Write new settings to XBee Flash ( ATWR )";
util.writeToSerialPort(fd,msg6);
qDebug() << "XBee written to, waiting for it to write to flash...";
while (true) {
int readNumberOfBytes = util.readFromSerialPort(fd,rxBuffer,4096);
printf("Received ( %d bytes ): %s\n", readNumberOfBytes,rxBuffer);
break;
}
// Close the file descriptor
close(fd);
}
Read:
void xbee::xbeeRead(char* usbPort) {
// Sleep
QWaitCondition waitCondition;
QMutex mutex;
waitCondition.wait(&mutex, 5000);
// Utils
Linuxutils util;
// File descriptor
int fd = util.openSerialPort(usbPort);
// Continually Read
char buffer[4096];
while (true) {
// Sleep
waitCondition.wait(&mutex, 1000);
qDebug() << "Waiting for data...";
int readNumberOfBytes = util.readFromSerialPort(fd,buffer,4096);
// Print results
printf("Read ( %d bytes ): %s\n", readNumberOfBytes,buffer);
}
// Close
close(fd);
}
Write:
void xbee::xbeeWrite(char *usbPort) {
// Sleep
QWaitCondition waitCondition;
QMutex mutex;
waitCondition.wait(&mutex, 5000);
// Utils
Linuxutils util;
// File descriptor
int fd = util.openSerialPort(usbPort);
// Continually Write
char *buffer = "Hello World!\n";
while (true) {
// Sleep
waitCondition.wait(&mutex, 1000);
int readNumberOfBytes = util.writeToSerialPort(fd,buffer);
// Print results
printf("Wrote ( %d bytes ): %s\n", readNumberOfBytes,buffer);
}
}
I can definitely configure each module - here is the example output for configuring ttyUSB0:
Input test type: 4
Opening Serial Port: "/dev/ttyUSB0"
Done opening Serial Port "/dev/ttyUSB0" : 6
Did configure port successfully? 0
Writing config string to XBee ( +++ )
XBee written to, waiting for response of 'OK'
Received ( 3 bytes ): OK
Check if XBee is responding ( AT )
XBee written to, waiting for response of 'OK'
Received ( 3 bytes ): OK
Get XBee PAN ID ( ATID )
XBee written to, waiting for response which is integer of current PAN
Received ( 5 bytes ): 3137
Check if XBee is responding ( ATID 3137 )
XBee written to, waiting for response after telling it to change to PAN 3137
Received ( 3 bytes ): OK
Get XBee PAN ID ( ATID )
XBee written to, waiting for response which is integer of current PAN
Received ( 5 bytes ): 3137
Write new settings to XBee Flash ( ATWR )
XBee written to, waiting for it to write to flash...
Received ( 3 bytes ): OK
Waiting for data...
Even though I can see that I am writing to the ttyUSB1 device in one while loop, I am not receiving anything at ttyUSB0.
Any ideas as to why this is happening?? Thanks!

Looks like you still have both XBees in command mode which will prevent any RF data transfer between these radio modules. Any serial data sent to the XBee will be ignored unless the line begins with the "AT" command prefix.
After you are done configuring each XBee, issue the "ATCN" command to exit command mode (there should be no "OK" response).
Then any serial data you send to the XBee will be transmitted by its radio, and the RF data received by the (other) XBee will be output on its serial port for reading by your program.
To re-enter command mode on an XBee module, nothing should be sent to the XBee serial port for one second (which is the default guard time), send a three character string of "+++" (three plus signs within 1 second), and then silence for another one second. The XBee should respond with an "OK" prompt.
All of this is standard Hayes modem AT command behavior.

Related

How can I send more bytes using Bluez L2CAP?

I have the following code that connects to another machine using BlueZ and sends packets:
struct sockaddr_l2 addr = { 0 };
int s, status;
char dest[18] = "DC:FB:48:6B:BF:0B";
int socket1;
int32_t value = 0;
// allocate a socket
socket1 = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
// set the connection parameters (who to connect to)
addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = htobs(0x1001);
str2ba( dest, &addr.l2_bdaddr );
status = connect(socket1, (struct sockaddr *)&addr, sizeof(addr));
while( status != 0)
{
status = connect(socket1, (struct sockaddr *)&addr, sizeof(addr));
std::cout << "Waiting for DC:FB:48:6B:BF:0B" << std::endl;
sleep(2);
}
while (true)
{
double data[512] = {0.0};
memset(data, 0, 512);
status = write(socket1, data, 512);
}
As you can see, I just send 512 bytes and other machine reads them just fine. However, when I try to increase to 1000 bytes, other machine can no longer accept any bytes and just does nothing.
How can I send more bytes in this case? I am using Linux CentOS 8.
By default the maximum transmission rate of L2CAP is 672 bytes. I would recommend you to try setting the maximum transmission unit to your required value.
Have a look at "4.3.1 Maximum Transmission Unit" here.

Use Arduino for reading accelerometer data & save to raspi

I want to use Arduino to read data from ADXL345 accelerometer and use raspberry pi with Processing to save the data into a txt file in pi. I used the code from https://www.researchgate.net/post/How_can_I_save_data_directly_in_the_pc_using_an_Arduino_UNO
And my Arduino code is shown as follows:
#include <Wire.h>
#define DEVICE (0x53) //ADXL345 device address
#define TO_READ (6) //num of bytes we are going to read each time (two bytes for each axis)
byte buff[TO_READ] ; //6 bytes buffer for saving data read from the device
char str[512]; //string buffer to transform data before sending it to the serial port
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
//Turning on the ADXL345
writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}
void loop()
{
int regAddress = 0x32; //first axis-acceleration-data register on the ADXL345
int x, y, z;
readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
//each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
//thus we are converting both bytes in to one int
x = (((int)buff[1]) << 8) | buff[0];
y = (((int)buff[3])<< 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];
//we send the x y z values as a string to the serial port
sprintf(str, "%d %d %d", x, y, z);
Serial.print(str);
Serial.write(10);
//It appears that delay is needed in order not to clog the port
delay(15);
}
void writeTo(int device, byte address, byte val) {
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); //end transmission
}
void readFrom(int device, byte address, int num, byte buff[]) {
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); //sends address to read from
Wire.endTransmission(); //end transmission
Wire.beginTransmission(device); //start transmission to device (initiate again)
Wire.requestFrom(device, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) //device may send less than requested (abnormal)
{
buff[i] = Wire.read(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
Processing code is shown as follows:
import processing.serial.*;
Serial mySerial;
PrintWriter output;
void setup() {
mySerial = new Serial( this, Serial.list()[0], 9600 );
output = createWriter( "/home/pi/data.txt" );
}
void draw() {
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed() {
output.flush(); // Writes the remaining data to the file
output.close(); // Finishes the file
exit(); // Stops the program
}
When only use serial monitor window to show x, y, z values, it looks well, but when using Processing to get data while Arduino serial monitor window is running, the data format changes, e.x. wrong format
Please help me.

Can a serial port be left in a dirty state?

I'm writing a program to communicate with an existing device via serial port, and I am noticing a weird pattern. This is being tested with both a real serial port, and a USB-to-serial adapter. I get the same results for both.
Immediately after booting up the computer or plugging in the adapter, serial port communication works fine. I can send binary data to the device, and get a response back. The program can continue to communicate with the device as long as it wants.
However, once the program ends (cleanly closing the port), running the program again results in failure to communicate. It can access the serial port just fine, but all it gets back is garbage.
(Oddly, the garbage appears to be binary data mixed with modem commands like ATE0Q0S0=0, which makes no sense. Again, I don't need to reset the device to communicate with it, just the port, so I don't know where this is coming from.)
Power-cycling or unplugging the device has no effect. It is only when I reboot the computer, or reset the USB device (via unplug, or driver reset), that I can run the program once more and get it to communicate successfully.
What would cause this? From the results, I can only assume that the serial port is not being left in a clean state after use, but I can find no documentation about properly cleaning the serial port state, other than re-applying ioctl attributes and closing the file descriptor after use, both of which I already do.
Maybe a serial port pin gets left on or something? I don't know how I would test for that, or why it would even happen.
My current "solution" is to just stick with the USB adapter, and have my program perform a USB driver reset before attempting to use the serial port, but I'm hoping there is a better solution.
Edit
As requested, here is the C program I'm using to test the serial port read/write.
include
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
// Saved termios that we can re-apply when we exit
struct termios savedPortAttributes;
// Set the serial port attributes so we can use it
void setPortAttributes( int fd )
{
struct termios tty;
memset( &tty, 0, sizeof(tty) );
if ( tcgetattr( fd, &tty ) != 0 ) {
printf( "tcgetaddr error: $i\n", errno );
return;
}
cfsetispeed( &tty, B9600 );
cfsetospeed( &tty, B9600 );
cfmakeraw( &tty );
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 5;
if ( tcsetattr( fd, TCSANOW, &tty ) != 0 ) {
printf( "tcsetaddr error: $i\n", errno );
return;
}
if ( tcflush( fd, TCIOFLUSH ) != 0 ) {
printf( "tcflush error: $i\n", errno );
return;
}
}
void test( int fd )
{
// Send a sample MODBUS command
printf( "Writing command\n" );
char sendBuffer[] = { 0x01, 0x03, 0x00, 0x0B, 0x00, 0x02, 0xB5, 0xC9 };
int bytesWritten = write( fd, sendBuffer, sizeof(sendBuffer) );
if ( bytesWritten < 0 ) {
printf( "Error writing command.\n" );
return;
}
// We don't want to wait more than 1000ms for a response
struct timespec spec;
clock_gettime( CLOCK_MONOTONIC, &spec );
int64_t startMs = spec.tv_sec * 1000 + round( spec.tv_nsec / 1.0e6 );
// Read data back from the port
printf( "Reading from port...\n" );
unsigned char buffer[1024];
int bufferOffset = 0;
int count = 0;
while ( 1 ) {
count = read( fd, &buffer[bufferOffset], sizeof(buffer) - bufferOffset );
if ( count < 0 ) {
printf( "Error reading command.\n" );
return;
}
if ( count > 0 ) {
printf( "Bytes read: " );
for ( int i = bufferOffset; i < bufferOffset + count; i++ ) {
printf( "%02x ", buffer[i] );
}
printf( "\n" );
}
bufferOffset += count;
// Test code. If we receive part of a valid MODBUS response, grab the
// field length byte so we know if we're done reading
if ( bufferOffset >= 3 && buffer[0] == 1 && buffer[1] == 3 ) {
int messageLength = buffer[2];
if ( bufferOffset >= messageLength + 5 ) {
break;
}
}
// If it's been 1000ms, stop reading
clock_gettime( CLOCK_MONOTONIC, &spec );
int64_t timeMs = spec.tv_sec * 1000 + round( spec.tv_nsec / 1.0e6 );
//printf( "%" PRId64 " , %" PRId64 "\n", startMs, timeMs );
if ( timeMs - startMs > 1000 ) {
break;
}
}
}
void main()
{
printf( "Opening port\n" );
int fd = open( "/dev/ttyUSB0", O_RDWR|O_NOCTTY );
if ( fd == -1 ) {
printf( "Unable to open port.\n" );
return;
}
tcgetattr( fd, &savedPortAttributes );
setPortAttributes( fd );
test( fd );
test( fd );
tcsetattr( fd, TCSANOW, &savedPortAttributes );
close( fd );
}

Linux Netcat works as Expected but not QTCPSocket on Raspberry Pi

I have 2 Raspberry Pis, one sender and one receiver which acts as an Access Point using a USB WiFi dongle. I have Qt 5.4.0 code on the sender that uses a USB/FTDI XBee SB6 WiFi unit to send TCP packets to the receiver Pi after connecting to it's Access Point successfully as a client.
The code is sending TCP packets correctly through the XBee to the receiver Pi because I can use the Netcat program on the receiver and watch the packets arrive successfully on port 0x2616 ( 9750 ):
>> sudo nc -l 10.10.10.1 9750
>> HELLOHELLOHELLO
When I try to replace Netcat on the receiver Pi with the following Qt code using QTCPSocket, it never receives any data on the socket. By this I mean that the 'readyRead()' slot is never called. I've run it as sudo and the sender Pi is doing exactly the same transfer as it was when Netcat was capturing the output. What is going on? Am I connecting wrong with QTCPSocket to the local port? How can I make it work? Thanks!
#include "tcpreceiver.h"
// Debug
#include <QDebug>
#define API_DEBUG true
#include <QApplication>
TcpReceiver::TcpReceiver(QObject *parent) :
QObject(parent)
{
// Debug
qDebug() << "Setting up a TCP Socket...";
// Create a socket
m_Socket = new QTcpSocket(this);
// Bind to the 2616 port
m_Socket->connectToHost("10.10.10.1", 0x2616);
//m_Socket->connectToHost( QHostAddress::Any, 0x2616 );
qDebug() << "Socket is valid: " << m_Socket->isValid();
//qDebug() << "Socket value: " << m_Socket->
// Get notified that data is incoming to the socket
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
// Init to Zero
m_NumberTCPPacketsReceived = 0;
}
void TcpReceiver::readyRead() {
qDebug() << "Received data...";
// When data comes in
QByteArray buffer;
buffer.resize(m_Socket->bytesAvailable());
// Cap buffer size
int lenToRead = buffer.size();
if ( buffer.size() > NOMINAL_AUDIO_BUFFER_SIZE ) {
lenToRead = NOMINAL_AUDIO_BUFFER_SIZE;
}
// Read the data from the TCP Port
m_Socket->read(buffer.data(), lenToRead);
...
// Count up
m_NumberTCPPacketsReceived++;
}
Here is how you do it:
#include "tcpreceiver.h"
// Debug
#include <QDebug>
#include <QHostAddress>
TcpReceiver::TcpReceiver(QObject *parent) :
QObject(parent)
{
// Create a server
qDebug() << "Creating a TCP Server...";
// Create the server
m_Server = new QTcpServer(this);
// Listen on the proper port
m_Server->listen( QHostAddress::Any, 0x2616 );
// Hook up signal and slots
connect(m_Server, SIGNAL(newConnection()), this, SLOT(gotNewConnection()));
connect(m_Server, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(error()));
}
void TcpReceiver::gotNewConnection() {
qDebug() << "Got a new TCP Connection";
// Get the socket
m_Socket = m_Server->nextPendingConnection();
if(m_Socket->state() == QTcpSocket::ConnectedState)
{
qDebug() << "Socket was connected at: " << m_Socket->peerAddress();
}
// Hook up some signals / slots
connect(m_Socket, SIGNAL(disconnected()),this, SLOT(disconnected()));
connect(m_Socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
}
void TcpReceiver::disconnected() {
qDebug() << "Socket Disconnected...";
// Cleanup
m_Socket->deleteLater();
}
void TcpReceiver::error() {
qDebug() << "Error: " << m_Server->errorString();
}
void TcpReceiver::readyRead() {
qDebug() << "Received data...";
// Now read data
QByteArray buffer;
if (m_Socket->canReadLine()) {
buffer = m_Socket->readLine();
qDebug() << "Got Data: " << buffer;
}
}

Segmentation fault in Thread pool

i am creating a bluetooth based server program in Bluez which basically handles connections from multiple devices. I have constructed two threads; one to scan the remote devices and another to connect with the devices that are broadcasting the service. Again, a separate thread is extracted from a thread pool for each of the newly connected devices which will then communicate with the server over a RFCOMM channel.
After establishing connection with a remote device, the server will send commands to the remote bluetooth device. Once the remote device a reply, the server reads that reply and stores it.
Now, the problem is whenever I get a reply back from the device the program crashes stating a "segmentation fault". Can anyone tell me a possible cause for this. The part of the code that does this is given here.
void startCommunication( int newSocket )
{
char buf[MODZ_MAX_DATA_SIZE] = "\0";
char previousData[ MODZ_MAX_DATA_SIZE ] = "\0";
time_t recvTime, prevRecvTime;
char dataToBeSent[ 4*MODZ_MAX_DATA_SIZE ] = "\0";
char *result;
if( sendDataToClient( newSocket, CMD_SEND) == EXT_ERROR ) //send acknowledgement first
printf("Couldn;t send ack\n");
else { printf("Date send woot! woot! %s\n", CMD_SEND); }
memset( buf, '0', sizeof(buf) );
while( 1 ){
recvTime = time( ( time_t * )0 );
if( readDataFromClient( newSocket, buf ) == EXT_ERROR ){
printf( "Read Error\n" );
break;
}
printf( "Data received = %s\n", buf );
strcpy( previousData, buf );
// store the data in a file and send to web
// check if the web has any data to send and if there is then send
result = "here we update the challenge";
strcpy( dataToBeSent, result );
free( result );
result = NULL;
//strcpy( buf, "We will soon update the database" );
if( sendDataToClient( newSocket, dataToBeSent ) == EXT_ERROR ){
break;
}
}
close( newSocket );
if( result != NULL ){
free( result );
}
printf( "\n****************Device disconnected***************\n" );
}
One obvious problem:
result = "here we update the challenge";
strcpy( dataToBeSent, result );
free( result );
You are freeing a pointer that was not allocated with malloc. That could well cause a segmentation fault.
In the future, try to use gdb to figure out exactly where your program crashes.

Resources