Go Down

Topic: Easy 2 way communication with an Arduino? (Read 987 times) previous topic - next topic

MikeX

Is there a library or something similar to make 2 way serial over USB communications easier? Something that will allow to query an Arduino, and it would return values, etc. I understand how to do it manually, just find it very messy. I've searched but haven't found anything that wrapped up that messiness into a library. Is there something out there?

billroy

Well, on the Arduino side you might consider Bitlash: http://bitlash.net

There are a lot of options on the PC side, but it really depends on what language you prefer.

For example: Here's a simple serial program uploader and terminal, written in node.js/javascript: https://github.com/billroy/bloader.js

If you prefer python instead: https://github.com/billroy/bloader.py

It might be possible to give a better answer if you said a little more about what you have in mind…

-br

PaulS

Quote
Is there a library or something similar to make 2 way serial over USB communications easier?

With an understanding of how serial data is transmitted (ssslllooowwwlllyyy), and a knowledge of what needs to be included in a serial data packet (start and end markers, for instance), receiving and sending serial data is dirt simple. I can't imagine why you need a library to complicate your life.

Quote
Something that will allow to query an Arduino

That will allow what to query an Arduino? What kind of questions is the Arduino supposed to be able to answer?

MikeX


Well, on the Arduino side you might consider Bitlash: http://bitlash.net
....
It might be possible to give a better answer if you said a little more about what you have in mind…


Bitlash is a good start, though seems much more powerful than what I really need.

I'm thinking of having a sketch with predefined functions, then being able to call those functions by name, pass in a variable or 2 to the function, etc. I'm not having trouble on the host side, the difficulty is on the Arduino side, more specifically parsing the input from the host. I haven't seen good examples of how to do it without any libraries, nor any helper libraries (except Bitlash, now).

billroy

#4
Oct 30, 2012, 12:40 am Last Edit: Oct 30, 2012, 12:41 am by billroy Reason: 1
It sounds like some small user functions in C and you'd be all set.  The tonedemo example might be a good starting point.

It's possible you could even write the functions in bitlash if they are relatively simple and not too time critical.  In which case you could just use the bitlashdemo example and start hacking.

-br

KeithRB

IF it is not too large, you could create an array of structs:

struct {
char Funcname[32];
void (*Funcptr)(void);
} funcs[32];

And initilise it with all your names and function addresses.
When a function name comes in, just scan the list for a match and then call the function.

But personally, I would use switch/case...

MikeX

I've looked at Bitlash more closely, and there is a limit on the length of function names, which pretty much makes the use of descriptive function names impossible...


But personally, I would use switch/case...


Can you please show an example of such a switch/case setup somewhere?

KeithRB

Actually, if/else might be cleaner.

char funcname[64];
int arg1, arg 2, arg 3;
// Parse function that separates function name from arguments
// resulting in
strcpy(funcname, "DoThisFunction");
arg1 = 1;
arg2 = 2;
arg3 = 3;

if (strcmp(funcname, "DoThisFunction") == 0) {
    DoThisFunction(arg1,arg2,arg3);
} else if (strcmp(funcname, "DoThatFunction") == 0) {
   DoThatFunction(arg1, arg2);
} else {
   //oops! No match error handling goes here
}

MikeX

KeithRB, the part that I find messy is reading the bytes from the serial stream, handling termination characters, etc... is there a complete sketch/example somewhere that will show how to do it?

KeithRB

Not that I know of, there are so many protocols and ways to parse the data, that it is diffcult to generalize. You might look at sketches that parse GPS NMEA strings for ideas.

If I understand your problem, I would send something like @DoThisFunc(1,2,3)

So your serial routine would wait for a character until it finds an "@", then start fillling a buffer with all the characters it finds until it gets to ")"

Then scan your string and break your string into pieces using the "(" and "," as separators. Do an atoi() on the arguments  and you are done.

There are ways to improve this, but I will leave it up to the interested student.

billroy

MikeX: If the function identifier length is the only concern you have about using bitlash, and twelve characters is not enough, you can easily change it to as big a number as you like subject to available ram.  Change the value of IDLEN at line 694 in src/bitlash.h and you should be good to go:

Code: [Select]

#define IDLEN 12    // make this bigger if 12 is not enough


Best,

-br

billroy

For serial port mechanics, you can see how Bitlash assembles a line of text and hands it off to the parser here:

https://github.com/billroy/bitlash/blob/master/src/bitlash-cmdline.c

-br

AMPS-N

can some share parse code in c to extract data gps data from gps sensor .

i tried  below code : where i can seprate data but i cant use in other source file

can some share the predefine function that call gps latitude, longitude, date, time, status from RMC data.
provide it support arduino UNO or deumilavo board

or let me know how can extract gps latitude, longitude, date, time, status from RMC data.  through function in same program

#include <string.h>
#include <ctype.h>
int ledPin = 13;                  // LED test pin
int rxPin = 0;                    // RX PIN
int txPin = 1;                    // TX TX
int byteGPS=-1;
char linea[300] = "";
char comandoGPR[7] = "$GPRMC";
char gps_time[25],gps_status[5],gps_latitude[20],gps_indl[5],gps_longitude[20],gps_indlong[5],gps_NS[10],gps_date[10],gps_head[8],gps_EW[8],gps_mode[5],gps_checksum[8],gps_mag[10];
char *temp;
int varcnt=0;
int cont=0;
int bien=0;
int conta=0;
int indices[13];
float time,latitude,longitude,date,lat_ind,long_ind,Status;

int k;
int m;
void setup() {
   pinMode(ledPin, OUTPUT);       // Initialize LED pin
   pinMode(rxPin, INPUT);
   pinMode(txPin, OUTPUT);
   Serial.begin(9600);
   for (int i=0;i<300;i++){       // Initialize a buffer for received data
     linea=' ';
   }   
}
void loop() {
   digitalWrite(ledPin, HIGH);
   byteGPS=Serial.read();         // Read a byte of the serial port
   if (byteGPS == -1) {           // See if the port is empty yet
    // delay(50);
   } else {
     linea[conta]=byteGPS;        // If there is serial port data, it is put in the buffer
     conta++;                     
    // Serial.print(byteGPS, BYTE);
     if (byteGPS==13){            // If the received byte is = to 13, end of transmission
       digitalWrite(ledPin, LOW);
       cont=0;
       bien=0;
       for (int i=1;i<7;i++){     // Verifies if the received command starts with $GPR
         if (linea==comandoGPR[i-1]){
           bien++;
         }
       }
       if(bien==6){               // If yes, continue and process the data
         for (int i=0;i<300;i++){
           if (linea==','){    // check for the position of the  "," separator
             indices[cont]=i;
             cont++;
           
               
           }
           if (linea=='*'){    // ... and the "*"
             indices[12]=i;
             cont++;
           }
         }
         Serial.println("");      // ... and write to the serial port
         Serial.println("");
         Serial.println("---------------");
         for (int i=0;i<12;i++){
           switch(i){
            case 0 :Serial.print("Time in UTC (HhMmSs): ");temp=gps_time;break;
             
            case 1 :Serial.print("Status (A=OK,V=NOT OK): ");temp=gps_status; break;
             case 2 :Serial.print("Latitude: ");temp=gps_latitude; Serial.println("");break;
             case 3 :Serial.print("Direction (N/S): ");temp=gps_indl; Serial.println("");break;
             case 4 :Serial.print("Longitude: ");temp=gps_longitude; Serial.println("");break;
             case 5 :Serial.print("Direction (E/W): ");temp=gps_indlong; Serial.println("");break;
             case 6 :Serial.print("velocity knots: ");temp=gps_NS;break; 
             case 7 :Serial.print("Heading in degrees: ");temp=gps_head;break;
              case 8:Serial.print("Date UTC (DdMmAa): ");temp=gps_date; Serial.println("");break;
               case 9 :Serial.print("Magnetic degrees: ");temp=gps_mag;break;
               case 10 :Serial.print("(E/W): ");temp=gps_EW;break;
               case 11 :Serial.print("Mode: ");temp=gps_mode;break;
                case 12 :Serial.print("Checksum: ");temp=gps_checksum;break;
             
             
                         }
          varcnt=0;
           for (int j=indices;j<(indices[i+1]-1);j++){
             Serial.print(linea[j+1]);
            temp[varcnt]=linea[j+1];
            varcnt++;
               
           
           }             
           
           Serial.println("");
         
           
         }
         Serial.println("");
       
         
         float time=atof(gps_time);
       
         float latitude=atof(gps_latitude);
       
         float longitude=atof(gps_longitude);
       
         float date=atof(gps_date);
         
          Serial.print(time);
          Serial.print(gps_status);
           Serial.print(latitude);
            Serial.print(gps_indl);
             Serial.print(longitude);
              Serial.print(gps_indlong);
               Serial.print(date);
          Serial.print("");
         sprintf(gps_time,"%f",time);
         
         
         
         
         
         
         
            Serial.print("");
         
         Serial.println("---------------");
             
         
       }
       conta=0;                    // Reset the buffer
       for (int i=0;i<300;i++){    // 
         linea=' ';             
       }                 
     }
   }
}
AMPS

Go Up