send packet to UBX protocol - c++

lately I have been working on a GPS reciever that supports both UBX and NEMA protocols. I am using serial programing on C++. I am trying to use UBX protocol, but it seems that I only recieve from NEMA. I downloaded the driver and I think I need to send a package first to recieve through UBX. Does anyone know a link or could tell me how could I send these packages the method I developed is stated below I think I need a small command before I start reading the data. Please someone help me here :D
void read_port(void)
{
unsigned char c='D';
while (c!='q')
{
if (read(fd, UBX_buffer, sizeof(UBX_buffer))>0)
{
data = read(fd, UBX_buffer, sizeof(UBX_buffer));
// write(fd,&UBX_buffer,1); // if new data is available on the serial port, print it out
cout<<"Data on the port = ";
for (unsigned i =0; i< sizeof(UBX_buffer) ;i++){
cout<<&UBX_buffer[i];
}
cout<<" "<<endl;
for (int i=0; i<fd; i++) // Process bytes received
{
switch(UBX_step) //we start from zero and increment as we go through the cases
{
case 0:
if(data==0xB5) UBX_step++; break; // UBX sync char 1 //check for the first data packet and go to next byte
case 1: if(data==0x62) UBX_step++;// UBX sync char 2 //check for the second data packet and go to the next byte
else UBX_step=0; break; //if first and second packets are not correct then go back and check again
case 2: UBX_class=data; checksum(UBX_class); UBX_step++; break;
case 3: UBX_id=data; checksum(UBX_id); UBX_step++; break;
case 4: UBX_payload_length_hi=data; checksum(UBX_payload_length_hi); UBX_step++; break;
case 5: UBX_payload_length_lo=data; checksum(UBX_payload_length_lo); UBX_step++; break;
case 6: // Payload data read...
if (UBX_payload_counter < UBX_payload_length_hi) // We stay in this state until we reach the payload_length
{
UBX_buffer[UBX_payload_counter] = data;
checksum(data);
UBX_payload_counter++;
}
else
UBX_step++;
break;
case 7: ck_a=data; UBX_step++; break; // First checksum byte
case 8: ck_b=data; // Second checksum byte
// We end the GPS read...
if((ck_a= ck_a)&&(ck_b= ck_a)) // Verify the received checksum with the generated checksum..
parse_ubx_gps(); // Parse new GPS packet...
UBX_step=0;
UBX_payload_counter=0;
ck_a=0;
ck_b=0;
GPS_timer=0; //Restarting timer...
break;
}
}
if (read(STDIN_FILENO,&c,1)>0) write(fd,&c,1); // if new data is available on the console, send it to the serial port
}
close(fd);
} // End Switch
} // End For

At the ublox Homepage you can Download the ublox protocoll specification. There, look at the cfg messages. For test purposes, you also can enable the ubx protocol via the tool u-Center.

Related

ffmpeg - avcodec_receive_frame returns -11, why and how to solve it?

I'm learning to use ffmpeg in my engine,
and I wanna decode the first frame of video stream and output it to an image file.
I tried and just can't figured out why it returns -11.
My code:(error in last 5 lines of code, line 70-74)
Link to my code
This is your code (line 70 - 74):
res = avcodec_receive_frame(pCodecContext, pFrame);
if (res != 0)
{
return EXIT_FAILURE;
}
Let's see, what the documentation has to say about the related function (avcodec_receive_frame):
Returns
0: success, a frame was returned
AVERROR(EAGAIN): output is not available in this state - user must try to send new input
AVERROR(EOF): the decoder has been fully flushed, and there will be no more output frames
AVERROR(EINVAL): codec not opened, or it is an encoder > other negative values: legitimate decoding errors
You could just do the following:
switch (res) {
default: puts("unknown result"); break;
case 0: puts("success"); break;
case AVERROR(EAGAIN): puts("output is not available"); break;
//... you get the idea
}

Sampling keyboard input at a certain rate in C++

What I want to do is sampling the keyboard input at a certain rate (e.g. 10-20 Hz). I use a while loop that read from stdin (I use read because I want to read asynchronously, e.i. I don't want to press enter every time) and then I have a pause before a new cycle starts to keep the sampling frequency stable.
The user press left/right arrow to give a command (to a robot). If nothing is pressed, the output is 0.
The problem is that, during the pause, the stdin buffer is written (I suppose), and so the read will return an old input. The final result is that the output is delayed. So if I press left the output immediately change to 1, but when I release it takes some seconds to return to 0. I want to remove this delay.
My aim is to sample just the more recent key pressed, in order to synchronize user input and output command without delays. Is there a way? Thank you in advance.
This is the method I'm using:
void key_reader::keyLoop()
{
char c;
bool dirty = false;
int read_flag;
// get the console in raw mode
tcgetattr(kfd, &cooked);
memcpy(&raw, &cooked, sizeof(struct termios));
raw.c_lflag &= ~(ICANON | ECHO);
// Setting a new line, then end of file
raw.c_cc[VEOL] = 1;
raw.c_cc[VEOF] = 2;
tcsetattr(kfd, TCSANOW, &raw);
//FD_ZERO(&set); /* clear the set */
//FD_SET(kfd, &set); /* add our file descriptor to the set */
//timeout.tv_sec = 0;
//timeout.tv_usec = 10000;
if (fcntl(kfd, F_SETFL, O_NONBLOCK) == -1)
{
perror("fcntl:"); // an error accured
exit(-1);
}
puts("Reading from keyboard");
puts("---------------------------");
puts("Use arrow keys to move the turtle.");
ros::Rate r(10);
while (ros::ok())
{
read_flag = read(kfd, &c, 1);
switch (read_flag)
{
case -1:
// case -1: is empty and errono
// set EAGAIN
if (errno == EAGAIN)
{
//no input yet
direction = 0;
break;
}
else
{
perror("read:");
exit(2);
}
// case 0 means all bytes are read and EOF(end of conv.)
case 0:
//no input yet
direction = 0;
break;
default:
ROS_DEBUG("value: 0x%02X\n", c);
switch (c)
{
case KEYCODE_L:
ROS_DEBUG("LEFT");
direction = 1;
dirty = true;
break;
case KEYCODE_R:
ROS_DEBUG("RIGHT");
direction = -1;
dirty = true;
break;
}
}
continuos_input::input_command cmd;
cmd.type = "Keyboard";
cmd.command = direction;
cmd.stamp = ros::Time::now();
key_pub.publish(cmd);
r.sleep();
}
}
I feel that the issue is with your subscriber rather than publisher. I can see that you have used rate to limit the publishing rate to 10Hz. Do confirm the publishing rate using Topic Monitor in rqt. Also setting a lower queue size for the publisher might help. Can't give a more definitive answer without referring to your subscriber node.

Unreliable SPI byte array transfer from Arduino to Raspberry Pi

I'm working on a project that collects data from an Arduino Pro Mini and sends it using SPI to a raspberry Pi for storage.
The Pro Mini will be reading analog input and calculating voltage (once I finish), and passing values to the Pi when prompted using an ISR.
I'm using C/C++ for both platforms to keep it uniform. The slave code is snipped together using Arduino IDE and the master code is based off a BCM2835 SPI library example for the Pi.
Arduino code is meant to calculate a float value and pre-process the float value into an array of 4 bytes/chars (I'm shooting for binary because I think it is the best way to go).
Once prompted by the Pi, each byte is sent and will be recompiled into a float.
Here is what I have now:
Slave
/*************************************************************
ARDUINO BREAKER READ/SPI PRE-PROC/TRANSMIT CASES
****************************************************************/
/***************************************************************
Global Variables
***************************************************************/
byte command = 0; //command from PI
byte bytes[4]; //
int sensorVoltage, sensorCurrent; //eventual live reading vars
float Voltage, Current, RealCurrent, RealVoltage, Power;
/***************************************************************
Set Up
-designate arudino as slave
-turn on interrupts
***************************************************************/
void setup (void)
{
//debugging with serial monitor
Serial.begin(9600);
// Set up arduino as slave
pinMode(MOSI, INPUT);
pinMode(SCK, INPUT);
pinMode(SS, INPUT);
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
} // end of setup
/*************************************************************
Interrupt Service Routine
************************************************************/
// SPI interrupt routine
ISR (SPI_STC_vect)
{
delay(500); //for errors
// Create union of shared memory space
union
{
float f_var;
unsigned char bytes[4];
} u;
// Overwrite bytes of union with float variable
u.f_var = RealVoltage;
// Assign bytes to input array
memcpy(bytes, u.bytes, 4);
byte c = SPDR;
command = c;
switch (command)
{
// null command zeroes register
case 0:
SPDR = 0;
break;
// case a - d reserved for voltage
case 'a':
SPDR = bytes[3];
break;
// incoming byte, return byte result
case 'b':
SPDR = bytes[2];
break;
// incoming byte, return byte result
case 'c':
SPDR = bytes[1];
break;
// incoming byte, return byte result
case 'd':
SPDR = bytes[0];
break;
/** // case e -h reserved for current
case 'e':
SPDR = amps.b[0];
break;
// incoming byte, return byte result
case 'f':
SPDR = amps.b[1];
break;
// incoming byte, return byte result
case 'g':
SPDR = amps.b[2];
break;
// incoming byte, return byte result
case 'h':
SPDR = amps.b[3];
break;
// case i - l reserved for wattage
case 'i':
SPDR = watts.b[0];
break;
// incoming byte, return byte result
case 'j':
SPDR = watts.b[1];
break;
// incoming byte, return byte result
case 'k':
SPDR = watts.b[2];
break;
// incoming byte, return byte result
case 'l':
SPDR = watts.b[3];
break;**/
} // end of switch
} // end of interrupt service routine (ISR) SPI_STC_vect
/***************************************************************
Loop until slave is enabled by Pi.
****************************************************************/
void loop (void)
{
/*************************************************************
Read and Calculate
****************************************************************/
/**
sensorVoltage = analogRead(A2);
sensorCurrent = analogRead(A3);
Voltage = sensorVoltage*(5.0/1023.0);
Current = sensorCurrent*(5.0/1023.0);
RealCurrent = Current/0.204545;
RealVoltage = (Voltage/0.022005);
Power = RealVoltage*RealCurrent;
**/
RealVoltage = 1.234;
/*************************************************************
Loop Check for SS activation
****************************************************************/
// if SPI not active, clear current command, else preproc floats and pass to SPI
if (digitalRead (SS) == HIGH){
command = 0;
}
/*************************************************************
Debug with serial monitor
****************************************************************/
/*
Serial.print("Byte 3: ");
Serial.println(bytes[3],BIN);
delay(500);
Serial.print("Byte 2: ");
Serial.println(bytes[2],BIN);
delay(500);
Serial.print("Byte 1: ");
Serial.println(bytes[1],BIN);
delay(500);
Serial.print("Byte 0: ");
Serial.println(bytes[0],BIN);
delay(1000);
Serial.println();*/
}
Master
#include <bcm2835.h>
#include <stdio.h>
void setup()
{
bcm2835_spi_begin();
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST); // The default
bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // The default
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default
}
char getByte(const char command){
char read_data = bcm2835_spi_transfer(command);
delay(100);
return read_data;
}
int main(int argc, char **argv)
{
//If you call this, it will not actually access the GPIO
//Use for testing
//bcm2835_set_debug(1);
if (!bcm2835_init())
return 1;
setup();
//Start communication
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);// Enable 0
//voltage 1-4
char read_data = getByte('a');
printf("byte is %02d\n", read_data);
read_data = getByte('b');
printf("byte is %02d\n", read_data);
read_data = getByte('c');
printf("byte is %02d\n", read_data);
read_data = getByte('d');
printf("byte is %02d\n", read_data);
/** voltage = volts.f;
printf("%.6f", voltage);
printf("\n");
**/
delay(1000);
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, HIGH);
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);// Disable 0
bcm2835_spi_end();
bcm2835_close();
return 0;
}
I'm using a fixed value to debug the code. Sometimes the output from SPI on the Pi is accurate, but otherwise it changes and outputs partially accurate and/or random bytes.
The issue I have been unable to work out is stability on the side of the Pi, so I am looking for help evaluating whether my code is causing inaccuracies or if it's my hardware.
At a guess I would say that this is a timing issue between the sender and receiver. Try looking at the bits of the data that you are receiving and see if they are shifted forward or backward. This will possibly indicate that the pi is waiting too long to begin receiving, or not waiting long enough for all of the data. I think the issues are probably around the delays:
delay(500); //for errors
on the Arduino, and
delay(1000);
on the receiver. Why are you using these? 500ms is a long time to keep the pi waiting for a response to the SPI data.
Just a note, there is also now an SPI kernel driver (spidev) for the pi - this is a much more industry standard approach, and is potentially a more robust method.
There's a good example of this on the raspberry pi github site: https://github.com/raspberrypi/linux/blob/rpi-4.4.y/Documentation/spi/spidev_test.c

Manage stream client server with Qt

I wonder how complex software client-server manage stream.
For example when I play counter strike, they are lots of packet send from client to server and server to clients. What is the best method to manage stream ?
I think :
Server send data to client
void Server::send(const QString &message)
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint16) 0; //packet size
out << (quint8)14; //packet type to execute a special action on the client
out << message; // data, here string but can be another class
out.device()->seek(0);
out << (quint16) (paquet.size() - sizeof(quint16)); //write packet size
socket->write(paquet);
}
Client receive data from server
void Client::receiveData()
{
QDataStream in(socket);
if (size_packet == 0) // size_packet, initilize to 0
{
if (socket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> tailleMessage;
}
if (socket->bytesAvailable() < tailleMessage)
return;
//now I can get data
quint8 typeObject;
in >> typeObject;
switch(typeObject){
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
...
...
case 14:
QString data; //can be another custom class
in >> data;
write(data);
break;
//my solution, the server can execute an action on the client depending type packet
}
size_packet= 0;
}
I guess I have to use a shared library between the client and the server and serialized my custom class.
But should I do otherwise? Use json or xml or protocol buffer (google) or something else ???
As #MrEricSir mention, games usually use UDP protocol. It uses datagrams, not streams. So some datagrams can be lost during data transmission. You protocol should work with data lost. Often such protocol are binary, they do not use xml, json or protobuf because of overhead.

Serial Port Driver-Got stuck in SerialISR () routine

I am writing windows device driver first time for multiport serial pci card.May be this one is stupid question but i got stuck.Need someone's help.Let me first explain what I have done yet.I have bus driver which creates number of child (2/4/8/16) depends on card. Now I have to write function driver for it.The bus driver creates interrupt which I have to use.Now in my driver I got bus interface,interrupt created in bus driver and related information.I am using Serial Port Driver Sample for reference.Now in SerialISR () routine my driver got stuck in while loop.
ServicedAnInterrupt = TRUE;
do {
InterruptIdReg &= (~SERIAL_IIR_FIFOS_ENABLED);
switch (InterruptIdReg) {
case SERIAL_IIR_RLS: {
READ_LINE_STATUS(Extension, Extension->Controller);
break;
}
case SERIAL_IIR_RDA:
case SERIAL_IIR_CTI: {
READ_RECEIVE_BUFFER(Extension, Extension->Controller);
break;
}
case SERIAL_IIR_THR: {
//
// Alread clear from reading the iir.
//
// We want to keep close track of whether
// the holding register is empty.
//
Extension->HoldingEmpty = TRUE;
break;
}
case SERIAL_IIR_MS: {
READ_MODEM_STATUS(Extension, Extension->Controller);
break;
}
default: {
ASSERT(FALSE);
break;
}
}
} while (!((InterruptIdReg =
READ_INTERRUPT_ID_REG(Extension, Extension->Controller))
& SERIAL_IIR_NO_INTERRUPT_PENDING));
Every time it goes into case SERIAL_IIR_MS. This process continue for some time about 1 min & then test pc will crash.What can be the reason behind that & what should I do to overcome this problem?I have gone through msdn library information. Also read issues regarding this on OSR website.