I'm trying to send through radio apc220 from a C-xenomai program to and from an arduino Mega.
I have one task created for sending, and one for reading in the xenomai program.
The arduino side reads and the writes to serial.
The baud-rates are both equal and tried 9600 and 19200, but the data recieved is random data, and not the values sent.
C code (This is in a task with "rt_task_set_periodic(NULL, TM_NOW, TM_INFINITE);" and priority in task creation of 99). Values of bufferMotorX are constantly changing.
strcpy(buffer,bufferMotor1);
strcat(buffer,bufferMotor2);
strcat(buffer,bufferMotor3);
strcat(buffer,bufferMotor4);
fprintf(stderr,"sending...%s\n",buffer);
write(apcFd, buffer, CONTROLLER_BUFFER_SIZE);
Arduino side:
if (Serial.available() > 0) {
// read the incoming byte:
for (int i=0; i < 12; i++)
{
inputByte=Serial.read();
inputBuffer[i]=inputByte;
}
bufferMotor1[0]=inputBuffer[0];
bufferMotor1[1]=inputBuffer[1];
bufferMotor1[2]=inputBuffer[2];
/*bufferMotor2[0]=inputBuffer[3];
bufferMotor2[1]=inputBuffer[4];
bufferMotor2[2]=inputBuffer[5];
bufferMotor3[0]=inputBuffer[6];
bufferMotor3[1]=inputBuffer[7];
bufferMotor3[2]=inputBuffer[8];
bufferMotor4[0]=inputBuffer[9];
bufferMotor4[1]=inputBuffer[10];
bufferMotor4[2]=inputBuffer[11];*/
Serial.print("I received: ");
Serial.println(bufferMotor1);
motor1=atoi(bufferMotor1);
Any ideas on what I'm doing wrong?
Related
I have tried to write wireless servo control using two arduino nano v3 boards and two bluetooth 4.0 modules. First code is transmitter. It's very simple. It reads PPM signals and transform to separates PWM values for each channel. I use hardware serial port.
#include <PPMReader.h>
#include <InterruptHandler.h>
int ppmInputPin = 3;
int channelAmount = 2;
PPMReader ppm(ppmInputPin, channelAmount);
void setup()
{
Serial.begin(9600);
Serial.write("AT\r\n");
delay(10);
Serial.write("AT\r\n");
Serial.write("AT+INQ\r\n");
delay(5000);
Serial.write("AT+CONN1\r\n");
}
void loop()
{
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
Serial.println(value1);
}
Receiver is simple too. It reads values from bluetooth and parse into integer value and sends to servo by 7th pin. Again I have used hardware serial port.
#include <Servo.h>
int PWM_OUTPUT = 7;
Servo servo;
void setup() {
servo.attach(PWM_OUTPUT);
Serial.begin(9600);
}
void loop() {
int pwmValue = Serial.parseInt();
if (Serial.available()) {
if(pwmValue > 900 && pwmValue < 2001) {
servo.writeMicroseconds(pwmValue);
}
}
}
All it works. But it has delay around 2-3 seconds. Can be problem in "spamming" serial port?
The first thing you need to ask yourself when implementing a device-to-device communication is how fast should I be sending? and if I send at that rate: is the receiver going to be able to keep pace (reading, doing processing or whatever it needs to do and answer back)?
This is obviously not about the baud rate but about what your loops are doing. You are using two different libraries: PPMReader and Servo. Now, pay attention to what each device is doing in their respective loops:
//Sending
void loop() {
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
Serial.println(value1);
}
//Receiving
void loop() {
int pwmValue = Serial.parseInt();
if(pwmValue > 900 && pwmValue < 2001) {
servo.writeMicroseconds(pwmValue);
}
}
I don't really know how long it takes to execute each line of code (take a look here for some comments on that) but you cannot seriously expect both loops to magically synchronize themselves. Considering they are doing very different things (leaving out the serial part) dealing with different hardware, I would expect one of them to take significantly longer than the other. Think about what happens if that's the case.
As I said, I have no idea how long it takes to call ppm.latestValidChannelValue(1, 0) but for the sake of my argument let's say it takes 0.1 milliseconds. To have an estimate of the time it takes to complete one iteration around the loop you need to add the time it takes to print one (or two) bytes to the port with Serial.println(value1) but that's easier, maybe around 20-100 microseconds is a good ballpark figure. With these estimates, you end up reading 5000 times per second. If you are not happy or you don't trust my estimates I would suggest you do your own tests with a counter or a timer. If you do the same exercise for the other side of the link and let's say you get it's twice as fast, it runs 10000 times per second, how do you think it would happen with the communication? Yes, that's right: it will get clogged and run at snail pace.
Here you should carefully consider if you really need that many readings (you did not elaborate on what you're actually doing so I have no idea, but I lean on thinking you don't). If you don't, just add a delay on the sender's side to slow it down to a reasonable (maybe 10-20 iterations per second) speed.
There are other things to improve on your code: you should check you have received data in the buffer before reading it (not after). And you need to be careful with Serial.parseInt(), which sometimes leads to unexpected results but this answer is already too long and I don't want to extend it even more.
I found problem. It was in serial port spamming. I have added check if current value is not equal with previous value and it have started work and next small issue was in receiver. I read value before it was available.
#include <PPMReader.h>
#include <InterruptHandler.h>
int ppmInputPin = 3;
int channelAmount = 2;
PPMReader ppm(ppmInputPin, channelAmount);
volatile unsigned long previousValue1 = 0;
void setup()
{
Serial.begin(9600);
Serial.write("AT\r\n");
delay(10);
Serial.write("AT\r\n");
Serial.write("AT+INQ\r\n");
delay(5000);
Serial.write("AT+CONN1\r\n");
Serial.println("Transmitter started");
}
void loop()
{
unsigned long value1 = ppm.latestValidChannelValue(1, 0);
if(previousValue1 != value1) {
previousValue1 = value1;
Serial.println(value1);
}
}
I'm trying to build a raw data with ethernet frame via C code.
I built a packet (included Ethernet->IP->UDP->DHCP protocols) and sent it via the WiFi interface. I followed it via the Wireshark which prints out:
Ethernet2 -> Frame Check Sequence -> Incorrect, should be XXX.
I did not build an FCS data in my packet, I left the field blank.
Now, I can't find any simple function/code in C which does that. All the codes I found gave me a bad output.
Someone done it before and can share how to implement the FCS in the Ethernet packet?
Thank you in advance
FIX: it seems that FCS calculation is only optional, I added the IP checksum calculation instead and that was enough for the DHCP to pass.
Thanks.
try:
#define BYTE unsigned char
int fcs(BYTE* paquete,int n){
int byte,sum=0;
n++;
for(int j=0;j<=n;j++){
byte=paquete[j];
for(int i=0;i<8;i++){
if(j!=n && i<7){
sum = sum+(byte & 0x01);
byte = byte >> 1;
}
}
}
return sum;
}
I'm creating a mini web server in C.
The following function is supposed to read in data from the client computer.
The objective is to read the second piece of data after the first space. Each piece of incoming data is space separated.
For example, if the incoming data is:
GET /123/456
then I'd expect /123/456.
If the incoming data is:
GET /123/456 789
then I'd still expect /123/456.
This relevant fragment is from an external function that sets up a 10 KB buffer and calls the problematic function:
//nsock is a valid socket handle from an accept() call.
printf("CLIENT CONNECTION!\n");
char req[10000];long reqsz=10000;
getreq(req,&reqsz,nsock);
printf("Received %d bytes\n",reqsz);
printf("Data: %s\n",req);
"CLIENT CONNECTION!" appears on the screen, but "Received" does not appear if bufsize inside the function is a high value. If I set it to a low value like 16, or 100, then everything is displayed correctly. Why do large numbers like 5000 not work?
This is the problematic function:
//getreq params in: req=external buffer for data
// reqsz=size of external buffer. I set 10000
// nsock=valid socket pointer from accept()
//
//getreq params out: reqsz=actual size of data returned
// req=actual data
//
void getreq(char* req,unsigned long *reqsz,long nsock){
//bufsize=how many bytes to read at once. High values like 5000 cause a stall.
//buffer=buffer of data from recv call
const unsigned long ibs=*reqsz,bufsize=5000;
char buffer[ibs],*rp=req;
//spacect=# of spaces in data read
//szct=iterator variable
//mysz=total length of returned data
//bufct=buffer counter to prevent segfault
//recvsz=data size returned from recv or
// forced -2 if buffer hits capacity
// or 2nd space in returned data is found
unsigned long spacect=0,szct=0,mysz=0,bufct=0;
long recvsz=1;char *p=buffer;
//
//Expected data: GET /whatever HTTP/x.x but we
// want /whatever
//
//loop until 2nd space is found or
//ibs bytes of data have been processed
while (recvsz > 0 && bufct < ibs){
recvsz=recv(nsock, p, bufsize, 0);
if (recvsz < 1){break;}
for (szct=1;szct<=recvsz;szct++){
if (*p==' '){spacect++;if (spacect > 2){spacect=2;recvsz=-2;break;}}
if (spacect==1 && *p != ' '){mysz++;if (mysz <= *reqsz){*rp++=*p;}}
p++;bufct++;if (bufct > ibs){recvsz=-2;break;}
}
}
// Process rest of data to try to avoid client errors
while (recvsz == -2){
recvsz=recv(nsock, buffer, bufsize, 0);
}
*reqsz=mysz;
}
I'm doing reverse engineering about a ultrasound probe on the Linux side. I want to capture raw data from an ultrasound probe. I'm programming with C and using the libusb API.
There are two BULK IN endpoints in the device (2 and 6). The device is sending 2048 bytes data, but it is sending data as 512 bytes with four block.
This picture is data flow on the Windows side, and I want to copy that to the Linux side. You see four data blocks with endpoint 02 and after that four data blocks with endpoint 06.
But there is a problem about timing. The first data block of endpoint 02's and first data block of endpoint 06's are close to each other acoording to time. But in data flow they are not in sequence.
I see that the computer is reading the first data blocks of endpoint 02 and 06. After that, the computer is reading the other three data blocks of endpoint 02 and endpoint 06. But in USB Analyzer, the data flow is being viewed according to the endpoint number. The sequence is different according to time.
On the Linux side, I write code like this:
int index = 0;
imageBuffer2 = (unsigned char *) malloc(2048);
imageBuffer6 = (unsigned char *) malloc(2048);
while (1) {
libusb_bulk_transfer(devh, BULK_EP_2, imageBuffer2, 2048, &actual2, 0);
libusb_bulk_transfer(devh, BULK_EP_6, imageBuffer6, 2048, &actual6, 0);
//Delay
for(index = 0; index <= 10000000; index ++)
{
}
}
So that result is in picture as below
In other words, in my code all reading data is being read in sequence according to time and endpoint number. My result is different from the data flow on the Windows side.
In brief, I have two BULK IN endpoints, and they are starting read data close according to time. How is it possible?
It's not clear to me whether you're using a different method for getting the data on Windows or not, I'm going to assume that you are.
I'm not an expert on libusb by any means, but my guess would be that you are overwriting you data with each call, since you're using the same buffer each time. Try giving your buffer a fixed value before using the transfer method, and then evaluate the result.
If it is the case, I believe something along the lines of the following would also work in C:
imageBuffer2 = (unsigned char *) malloc(2048);
char *imageBuffer2P = imageBuffer2;
imageBuffer6 = (unsigned char *) malloc(2048);
char *imageBuffer6P = imageBuffer6;
int dataRead2 = 0;
int dataRead6 = 0;
while(dataRead2 < 2048 || dataRead6 < 2048)
{
int actual2 = 0;
int actual6 = 0;
libusb_bulk_transfer(devh, BULK_EP_2, imageBuffer2P, 2048-dataRead2, &actual2, 200);
libusb_bulk_transfer(devh, BULK_EP_6, imageBuffer6P, 2048-dataRead6, &actual6, 200);
dataRead2 += actual2;
dataRead6 += actual6;
imageBuffer2P += actual2;
imageBuffer6P += actual6;
usleep(1);
}
I'm continuously sending 2D arrays of pixel values (uint32) from LabVIEW to a C-program through TCP/IP with the resolution 160x120. The purpose of the C-program is to display the received pixel values as 2D arrays in the console application. I'm sending the pixels as stream of bytes, and using the recv function in Ws2_32.lib to receive the bytes in the C-program. Then I'm converting the bytes to uint32 values and displaying them in the console application using a 2D arrays, so every 2D array will represent an image.
I have en issue with the frame rate though. I'm able to send 30 frames per second in LabVIEW, but when I open the TCP/IP connection with the C-program, the frame rate goes down to 1 frame per second. It must be an issue with the C-program, since I managed to send the desired frames per second with the same LabVIEW program to a corresponding C# program.
The C-code:
#define DEFAULT_BUFLEN 256
#define IMAGEX 120
#define IMAGEY 160
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
int iResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
typedef unsigned int uint32_t;
unsigned int x=0,y=0,i,n;
uint32_t image[IMAGEX][IMAGEY];
size_t len;
uint32_t* p;
p = (uint32_t*)recvbuf;
do
{
iResult = recv(new_socket, recvbuf, recvbuflen, 0);
len = iResult/sizeof(uint32_t);
for(i=0; i < len; i++)
{
image[x][y] = p[i];
x++;
if (x >= IMAGEX)
{
x=0;
y++;
}
if (y >= IMAGEY)
{
y = 0;
x = 0;
//print image
for (n=0; n< IMAGEX*IMAGEY; n++)
{
printf("%d",image[n%IMAGEX][n/IMAGEY]);
if (n % IMAGEX)
{
printf(" ");
}
else
{
printf("\n");
}
}
}
}
} while ( iResult > 0 );
try reducing the prints .. Since you are reading and printing in the same thread, the data in the TCP connection will fill up and it will then back pressure the other end (LABView) and the LABView will stop sending data until it gets the green signal from the other end (you C program)
To start with you can debug by replacing this
for (n=0; n< IMAGEX*IMAGEY; n++)
{
printf("%d",image[n%IMAGEX][n/IMAGEY]);
if (n % IMAGEX)
{
printf(" ");
}
else
{
printf("\n");
}
}
with
printf("One frame recv\n");
and see if it makes any difference. I am assuming your tcp connection has ample bandwidth
Very hard to diagnose without further information. I can give a few suggestions, however.
First of all, your recv call is using a small buffer, so you are spending a lot of time calling it. Why not read a whole frame at a time? Also, you read in the data and then copy it to the image array. Wouldn't it be simpler to just use the image array itself? Combining those two suggestions would have recv reading a full frame directly into the image array, saving a lot of time.
Another source of the problem could be the console. With the sample code you provided, you are attempting to write 30*120*160=57,600 integer values per second to the terminal. If the average value, with delimiter, takes up 8 characters, that's 4 million characters per second. It's entirely possible that the display just can't go that fast, in which case things would back up and slow down all the way to the server writing to the socket.
There are several ways to handle this, but it's too much to go into here.