USB HOST SHIELD

Salve a tutti,
Ho una usb shield montata su un Arduino Mega a cui devo collegare un gps usb.
Ho scaricato la libreria usb host ed il codice relativo al acm funziona e mi fa vedere la stringa nmea.
Il problema sorge che non riesco a memorizzare tale stringa in una variabile di tipo String letturaGps necessaria per continuare le elaborazioni. Vi allego il codice sperando in un Vs aiuto.

#include <cdcacm.h>
#include <usbhub.h>

#include "pgmstrings.h"

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

class ACMAsyncOper : public CDCAsyncOper
{
public:
    uint8_t OnInit(ACM *pacm);
};

uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
    uint8_t rcode;
    // Set DTR = 1 RTS=1
    rcode = pacm->SetControlLineState(3);

    if (rcode)
    {
        ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
        return rcode;
    }

    LINE_CODING	lc;
    lc.dwDTERate	= 9600;
    lc.bCharFormat	= 0;
    lc.bParityType	= 0;
    lc.bDataBits	= 8;

    rcode = pacm->SetLineCoding(&lc);

    if (rcode)
        ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);

    return rcode;
}

USB     Usb;
//USBHub     Hub(&Usb);
ACMAsyncOper  AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

void setup()
{
  Serial.begin( 9600 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
      Serial.println("OSCOKIRQ failed to assert");

  delay( 200 );
}

void loop()
{
    Usb.Task();

    if( Acm.isReady()) {
       uint8_t rcode;

       /* reading the keyboard */
       if(Serial.available()) {
         uint8_t data= Serial.read();
         /* sending to the phone */
         rcode = Acm.SndData(1, &data);
         if (rcode)
            ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
       }//if(Serial.available()...

       delay(50);
String strNMEA;
        /* reading the phone */
        /* buffer size must be greater or equal to max.packet size */
        /* it it set to 64 (largest possible max.packet size) here, can be tuned down
        for particular endpoint */
        uint8_t  buf[64];
        uint16_t rcvd = 64;
        rcode = Acm.RcvData(&rcvd, buf);
         if (rcode && rcode != hrNAK)
            ErrorMessage<uint8_t>(PSTR("Ret"), rcode);

            if( buf!="\0") { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
                
              }
                String strNMEA = ((char*)buf);
                Serial.print(" strNMEA:  ");
                Serial.println(strNMEA);
                strNMEA="";
            }
        delay(10);
    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
}

Ciao,
ho provato questo, ma spezza la stringa in 2(una piu grande ed una piu piccola)

for(uint16_t i=0; i < rcvd-1; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
                str+=((char)buf[i]);
              }

Ma un semplice:

String strNMEA (buf);

non funziona? Ma soprattutto, sei sicuro di non poter fare a meno della classe String?

Ciao ho appena fatto la prova ma non va

if( rcvd) { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
                
              }
                String strNMEA (buf);
                Serial.println(buf);
                
            }

error: call of overloaded 'String(uint8_t [64])' is ambiguous

La necessita della string nasce dal fatto che successivamente devo vedere se la stringa che ottengo é quella che voglio effettuando un controllo con substring

Non avevo visto che era un uint8_t. Prova:

String strNMEA ((char *) buf);

Oppure, ancora meglio in C++:

String strNMEA (static_cast<char *> (buf));

(o forse qua ci vuole reinterpret_cast<>? :D)

Comunque non hai alcun bisogno di usare la classe String. Puoi fare lo stesso controllo direttamente sul buffer usando la funzione strstr().

niente da fare

if( rcvd) { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
                
              }
                String strNMEA (char*(buf));
                Serial.println(strNMEA);
                
            }

error: call of overloaded 'println(String (&)(char*))' is ambiguous

Prima utilizzavo la seriale ma adesso mi serve usare usb

g = GpsSerial.read();
            if (g != '\n')
              {
                strNMEA += g;
               
              }

sopra vedi il codice che usavo, per cui riuscivo a memorizzare su stringa tutto fino a \n

peppegti:
niente da fare

if( rcvd) { //more than zero bytes received

for(uint16_t i=0; i < rcvd; i++ ) {
               //Serial.print((char)buf[i]); //printing on the screen
               
             }
               String strNMEA (char*(buf));
               Serial.println(strNMEA);
               
           }





error: call of overloaded 'println(String (&)(char*))' is ambiguous

Io ho messo le parentesi in maniera diversa... E ti ho anche detto di provare altre due cose.

Ho fatto le due prove che mi dicevi sistemando le parentesi(sorry)

l'unica che funziona é rinterpreta ....ma dopo 5 sec si blocca o non parte proprio
inoltre ti allego l'output che come vedi e spezzettato

$GNTXT,01,01,02,LLC=FFFFFFFF-FFFFFFED-FFFFFFFF-FFFFF79E-FFFFFF692E
,49

$GNTXT,01,01,02,ANTSUPERV=AC SD PDoS SR
3E
FF-FFFFF79E-FFFFFF69
2E
,49

$GNTXT,01,01,02,ANTSTATUS=OK
25
DoS SR3E
FF-FFFFF79E-FFFFFF69
2E
,*49

Prima di:

rcode = Acm.RcvData(&rcvd, buf);

Prova ad aggiungere:

memset (buf, 0x00, sizeof (buf));

Io allargherei anche un po' il buffer, almeno 128, visto che a quanto pare non puoi nemmeno passare la sua dimensione alla Acm.RcvData() e quindi l'overflow è dietro l'angolo.

Se ancora non va, posta lo sketch intero com'è ora, altrimento non capiamo più niente.

eccolo qui perché non va bene.....si blocca ancora :sob:

#include <cdcacm.h>
#include <usbhub.h>

#include "pgmstrings.h"

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

class ACMAsyncOper : public CDCAsyncOper
{
public:
    uint8_t OnInit(ACM *pacm);
};

uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
    uint8_t rcode;
    // Set DTR = 1 RTS=1
    rcode = pacm->SetControlLineState(3);

    if (rcode)
    {
        ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
        return rcode;
    }

    LINE_CODING	lc;
    lc.dwDTERate	= 9600;
    lc.bCharFormat	= 0;
    lc.bParityType	= 0;
    lc.bDataBits	= 8;

    rcode = pacm->SetLineCoding(&lc);

    if (rcode)
        ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);

    return rcode;
}

USB     Usb;
//USBHub     Hub(&Usb);
ACMAsyncOper  AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

void setup()
{
  Serial.begin( 9600 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
      Serial.println("OSCOKIRQ failed to assert");

  delay( 200 );
}

void loop()
{
    Usb.Task();

    if( Acm.isReady()) {
       uint8_t rcode;

        String str;
        uint8_t  buf[128];
        uint16_t rcvd = 128;
        memset (buf, 0x00, sizeof (buf));
        rcode = Acm.RcvData(&rcvd, buf);
         if (rcode && rcode != hrNAK)
            ErrorMessage<uint8_t>(PSTR("Ret"), rcode);

        if( rcvd) { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
                
              }
                String strNMEA (reinterpret_cast<char *> (buf));
                Serial.println(strNMEA);
                
            }
        delay(10);

    }
}

Come vedi si blocca li
inoltre nella conversione non devo mettere -1?

ti allego anche il file .h

#if !defined(__PGMSTRINGS_H__)
#define __PGMSTRINGS_H__

#define LOBYTE(x) ((char*)(&(x)))[0]
#define HIBYTE(x) ((char*)(&(x)))[1]
#define BUFSIZE 256    //buffer size
 

/* Print strings in Program Memory */
const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; 
const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
const char Dev_Vendor_str[] PROGMEM ="\r\nVendor  ID:\t\t";
const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
 
#endif // __PGMSTRINGS_H__

Sai se la funzione Acm.RcvData() riceve un messaggio completo o potenzialmente solo una parte?

in che senso ? senza passare nulla?

allora ho fatto un paio di prove ed ecco cosa succede, praticamente resto fuori dal controllo if(rcvd) infatti dopo un paio di giri di lettura l output resta a 1

if( Acm.isReady()) {
       uint8_t rcode;

        String str;
        uint8_t  buf[128];
        uint16_t rcvd = 128;
        memset (buf, 0x00, sizeof (buf));
        rcode = Acm.RcvData(&rcvd, buf);
         if (rcode && rcode != hrNAK)
            ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
        Serial.println("  1  ");
        if( rcvd) { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
                Serial.println("  2  ");
                
              }
                String strNMEA (reinterpret_cast<char *> (buf));
                if (strNMEA.substring(0, 6) == "$GNGGA")
                {
                    Serial.print(strNMEA);
                    //strNMEA="";
                    
                    Serial.println("  3  ");
                }
            }
        delay(10);

    }

A questo punto io mi tiro indietro, non conosco quella libreria ed evidentemente non funziona come mi ero immaginato. Vediamo se qualcun altro ne sa di più.

Allora dopo un bel po di prove ho capito il problema, ti posto il codice pulito:

#include <cdcacm.h>
#include <usbhub.h>

#include "pgmstrings.h"

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

class ACMAsyncOper : public CDCAsyncOper
{
public:
    uint8_t OnInit(ACM *pacm);
};

uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
    uint8_t rcode;
    // Set DTR = 1 RTS=1
    rcode = pacm->SetControlLineState(3);

    if (rcode)
    {
        ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
        return rcode;
    }

    LINE_CODING  lc;
    lc.dwDTERate  = 9600;
    lc.bCharFormat  = 0;
    lc.bParityType  = 0;
    lc.bDataBits  = 8;

    rcode = pacm->SetLineCoding(&lc);

    if (rcode)
        ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);

    return rcode;
}

USB     Usb;
//USBHub     Hub(&Usb);
ACMAsyncOper  AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

void setup()
{
  Serial.begin( 9600 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
      Serial.println("OSCOKIRQ failed to assert");

  delay( 200 );
}

void loop()
{
    Usb.Task();

    if( Acm.isReady()) {
       uint8_t rcode;

       
       delay(50);

        /* reading the phone */
        /* buffer size must be greater or equal to max.packet size */
        /* it it set to 64 (largest possible max.packet size) here, can be tuned down
        for particular endpoint */
        uint8_t  buf[64];
        uint16_t rcvd = 64;
        memset (buf, 0x00, sizeof (buf));
        rcode = Acm.RcvData(&rcvd, buf);
         if (rcode && rcode != hrNAK)
            ErrorMessage<uint8_t>(PSTR("Ret"), rcode);

            if( rcvd ) { //more than zero bytes received
              for(uint16_t i=0; i < rcvd; i++ ) {
                //Serial.print((char)buf[i]); //printing on the screen
              }
            }
            String strNMEA(reinterpret_cast<char *> (buf));
            if (strNMEA.substring(0, 6) == "$GNGGA")
              Serial.println(strNMEA);
            strNMEA="";
        delay(10);
    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
    
}

output:

$GNGGA,090140.00,,,,,0,03,2.35,,,,,,*43

$GNGGA,090141.00,,,,,0,03,2.35,,,,,,*42

$GNGGA,090142.00,,,,,0,03,2.35,,,,,,*41

$GNGGA,090143.00,,,,,0,03,2.35,,,,,,*40

$GNGGA,090144.00,,,,,0,03,2.35,,,,,,*47

$GNGGA,090145.00,,,,,0,03,2.35,,,,,,*46

$GNGGA,090146.00,,,,,0,03,2.35,,,,,,*45

$GNGGA,090147.00,,,,,0,03,2.35,,,,,,*44

$GNGGA,090148.00,,,,,0,03,2.35,,,,,,*4B

ancora non ha fix.....ma vedi che ci sono 2 a capo, uno mio ed uno suo

Ecco cosa ho scoperto, se io lascio il buf e rcvd a 64 non si blocca, ma manca parte della stringa(anche se quando lascio il suo print di buf é completo.... :confused: )
quindi se aumento questi numeri prendo tutta la tringa su strNMEA.....ma si blocca random dopo 10 5 o 2 letture, se lascio 64 va avanti senza problema ogni secondo.....ma mancano caratteri come vedi sotto
* *$GNGGA,090453.00,0000.56712,N,0000.63488,E,1,09,1.18,967.2,M,37 $GNGGA,090454.00,0000.56721,N,0000.63480,E,1,09,1.18,966.8,M,37 $GNGGA,090455.00,0000.56739,N,0000.63469,E,1,09,1.18,966.4,M,37 $GNGGA,090456.00,0000.56700,N,0000.63488,E,1,09,1.18,965.6,M,37 $GNGGA,090457.00,0000.56690,N,0000.63496,E,1,09,1.18,965.0,M,37 $GNGGA,090458.00,0000.56665,N,0000.63494,E,1,09,1.18,964.4,M,37 //stringa corretta sotto $GNGGA,090649.00,0000.56991,N,0000.63471,E,1,09,1.20,960.8,M,37.5,M,,*4F* *
qualcuno sa risolvere questo mistero??????

Io ti faccio solo notare che, come già detto, usare la String non ti serve a niente e ti crea solo problemi di memoria:

char *cbuf = reinterpret_cast<char *> (buf);    // Ma non lo puoi mettere come char* fin da subito???
if (strstr (cbuf, "$GNGGA") != NULL) {
  // ...
}

E, visto che la RAM è preziosa, ancora meglio:

char *cbuf = reinterpret_cast<char *> (buf);    // Ma non lo puoi mettere come char* fin da subito???
if (strstr_P (cbuf, PSTR("$GNGGA")) != NULL) {
  // ...
}

Ciao, ho appena fatto la prova, funziona come dici tu nel secondo caso ma ho sempre la stringa non completa