0

I am new to serial interfacing and my company has asked me to design an API that configures a gyroscope -connected to a WIFI chip- using a C code, by sending the hex commands over a UDP socket to the WIFI chip. I made sure to adhere to the format provided by the manufacturer's manual but it seems that i am missing something when it comes to the serial interfacing aspect. I am using this code to do so:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "port.h"
#include <time.h>

void waitFor (unsigned int );

unsigned char head1 = 0xff; //head
unsigned char head2 = 0xaa;  //head2
unsigned char saveadd = 0x00; //saveconfig address
unsigned char savevalue = 0x00; //save config  0x01 is factory reset
unsigned char endd = 0x00; //end

int
main(int argc, char **argv)
{
    struct sockaddr_in myaddr;  /* our address */
    struct sockaddr_in remaddr; /* remote address */
    remaddr.sin_addr.s_addr = inet_addr("192.168.1.1");
    remaddr.sin_port = htons(8889);
    socklen_t addrlen = sizeof(remaddr);        /* length of addresses */
    int recvlen;            /* # bytes received */
    int fd;             /* our socket */
    int msgcnt = 0;         /* count # of messages we received */
    remaddr.sin_family = AF_INET;

    /* create a UDP socket */

    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("cannot create socket\n");
        return 0;
    }

    /* bind the socket to any valid IP address and a specific port */

    memset((char *)&myaddr, 0, sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(SERVICE_PORT);

    if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
        perror("bind failed");
        return 0;
    }



        printf("waiting on port %d\n", SERVICE_PORT);


        // Hex command that turns a builtin LED on
        unsigned char comPart1 =    0xFF;
        unsigned char comPart2 =    0xAA;
        unsigned char comPart3 =    0x1b;
        unsigned char comPart4 =    0x00;
        unsigned char comPart5 =    0x00;

        unsigned char commands [5]; /* unsigned char array to hold command */
        commands [0] = comPart1;
        commands [1] = comPart2;
        commands [2] = comPart3;
        commands [3] = comPart4;
        commands [4] = comPart5;




        unsigned char temp_buf [2]; /*buffer used to send hex command*/
        temp_buf [0]= (unsigned char) 0x00;
        temp_buf [1]= '\0';



        for (int i = 0; i < 5 ; i++) 
        {
           temp_buf [0] = commands[i];

        if (sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
            perror("sendto");
       }

        waitFor (0.5); /*delay specified by user manual*/



        printf ("%s \n", "Now saving the configration");
        //save commands as specified by user manual 
        unsigned char saveConfig [5];

        saveConfig [0] = head1;
        saveConfig [1] = head2;
        saveConfig [2] = saveadd;
        saveConfig [3] = savevalue;
        saveConfig [4] = endd;

        for (int i = 0; i < 5 ; i++)
        {

        temp_buf [0] = saveConfig [i];

        if (sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
            perror("sendto");
            waitFor (0.05);
       }
       waitFor (0.45);



}

void waitFor (unsigned int secs) {
    unsigned int retTime = time(0) + secs;   // Get finishing time.
    while (time(0) < retTime);               // Loop until it arrives.
}

I was able to configure the gyroscope serially (if disconnected from the WIFI chip and connected to a USB-TTL) using CuteCom. So i know that the hardware works. What am I missing when it comes to serial interfaces. How would one go about achieving such a task?

24
  • 3
    "serial interfacing" and sockets are two very different things. The code you presented uses sockets but you tested with CuteCom using a comm port (or serial port). Are you sure your device is configured properly for socket communications? Commented Aug 15, 2016 at 16:33
  • 2
    "I am essentially trying to send the following: 0xff 0xaa 0x1b 0x00 0x00". Looks like to me you are sending 0xff 0x00 0xaa 0x00 0x1b 0x00,, etc. The 0x00 byte isn't a magical/universal end-of-buffer byte. There must be some protocol the gyroscope is using, maybe a defined message size, or a maybe a byte sequence that signifies end-of-message. This should be in the documentation. It would be great if you could capture the serial traffic to see exactly what is being sent via CuteCom. Also, make absolute certain the WIFI is connected the way you think it is. Commented Aug 15, 2016 at 17:03
  • 1
    You are setting the length of each datagram (the 3rd parameter of sendto) to sizeof (temp_buf) which is 2. If you want to send a single byte per datagram, set the parameter to 1. What happens if you send the whole 5 byte command in a single datagram, e.g.: sendto(fd, commands, 5, 0, (struct sockaddr *)&remaddr, addrlen)? Commented Aug 15, 2016 at 17:15
  • 1
    when compiling, always enable all the warnings, then fix those warnings. for gcc, at a minimum use: -Wall -Wextra -pedantic I also use: -Wconversion -std=gnu99 Then you will get a sizeable list of of warnings from the compiler. For fixes, since parameters argc and argv are not used, the appropriate signature for main() is int main( void ) There are also several unused variables. Commented Aug 17, 2016 at 1:25
  • 1
    The parameter for the function: time() is either NULL or the address of a variable with type time_t The 0 is an iffy fit for NULL, Strongly suggest make the parameter NULL Commented Aug 17, 2016 at 1:27

2 Answers 2

2

you said/asked in the comments

I am essentially trying to send the following: 0xff 0xaa 0x1b 0x00 0x00 one byte at a time. Do you think the NULL (byte of zeros) are causing the issue? How would I indicate the end of the buffer if I am not to use it?

From your code, however, you are sending a NULL byte in-between each of these data bytes. temp_buf contains 2 bytes, you are hard-coding the second byte to \0 and setting the first byte to the data byte. Then the sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen line sends the contents of this buffer. If you trapped your network traffic in wireshark, you would see that you are sending 0xff 0x00 0xaa 0x00 0x1b 0x00 0x00 0x00 0x00 0x00 rather than what you intended to send.

To answer your questions, c strings aside, there is nothing universal about a NULL byte terminator for a buffer. Valid data bytes can be 0x00 all the time. If I email someone a black picture, I'll be sending a whole stream of 0x00 bytes. Your gyroscope must have some kind of protocol that should be described in its documentation. In my experience, this has been a fixed message length, a start/end sequence of "magic" bytes, or even an application-defined header. In your comments, you indicate the gyroscope simply wants one byte at a time, so there you go, just send it one byte at a time! I imagine you changed your code to something like the following:

// really no need for temp_buf
for (int i = 0; i < 5 ; i++)
{
  if (sendto(fd, &saveConfig[i] /* or saveConfig+i */, sizeof(char), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
  {
    perror("sendto");
    // I'm guessing from your indentation you want this wait inside the if-statement. Note that in the code you posted, the if-statement doesn't have any brackets so this will execute each time through the loop whether there is an error or not
    waitFor (0.05);
  }
  waitFor (0.45);
}

In general, any time you're dealing with network problems like this, I would strongly recommend using wireshark (or equivalent) to see exactly what you are sending,, it is extremely helpful!

Sign up to request clarification or add additional context in comments.

Comments

1

saveConfig is binary data but you need to send the hex representation so:

temp_buf [0] = saveConfig [i]

will not work.

What you need is something like:

unsigned int
gethex(unsigned int val,int shf)
{

    val >>= shf;
    val &= 0x0F;
    val = "0123456789ABCDEF"[val];

    return val;
}

temp_buf[0] = gethex(saveConfig[i],4);
temp_buf[1] = gethex(saveConfig[i],0);

1 Comment

Thats a good way of doing it. There was no issue in data representation. It was a matter of how the data was propagated. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.