[RESOLU] Comparer deux tableaux de unsigned char et int change le fonctionnement

Bonjour, j'explique mon probléme mais je l'ai résolu mais pourquoi.

j'ai deux tableaux de uint_8 (unsigned char)

unsigned char so_far[9] = {0,0,0,0,0,0,0,0,0};
unsigned char lengths[9] = {2,5,4,9,6,6,5,7,9};

dans mon application je comparais ces deux tableaux avec le même indice.
mais j'avais au niveau fonctionnement des problème aléatoire, j'ai cherché pendant deux jours.

du coup en changeant le type à int, ca à fonctionner, j'obtenais ce que je voulais

int so_far[9] = {0,0,0,0,0,0,0,0,0};
int lengths[9] = {2,5,4,9,6,6,5,7,9};

C'est juste sur le principe, ca doit dépendre de l'architecture ?
j'avoue que ce n'est pas un processeur arduino mais sur un ez80.

Merci.

je me suis trompé de catégorie, si quelqu'un peut le déplacer dans aide arduino programmation.

Bonjour @andromeda92

message déplacé à la racine du forum, comme spécifié dans les 'Bonnes Pratiques du Forum Francophone'

il nous faudrait le code qui faisait la comparaison... vous avez sans doute un bug...

for (uint8_t i = 0; i < 9; i++) {
   if (so_far[i] == lengths[i]) {
      ......
   }
}

idem, si la variable i dans la boucle je la déclare en int, la comparaison est aléatoire.

non ça fonctionne. Postez un code complet qui prouve ce que vous dites

essayez ce bout de code par exemple

unsigned char so_far[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char leMeme[9] = {2, 5, 4, 9, 6, 6, 5, 7, 9};
unsigned char lengths[9] = {2, 5, 4, 9, 6, 6, 5, 7, 9};
 
// retourne true si les tableaux sont identiques
bool compare (unsigned char tab1[9], unsigned char tab2[9]) {
  bool identiques = true;
  for (byte i = 0; i < 9; i++)
    if (tab1[i] != tab2[i]) {
      identiques = false;
      break;
    }
  return identiques;
}

void setup() {
  Serial.begin(115200);
  Serial.print("so_far versus lengths ==> "); Serial.println(compare(so_far, lengths) ? "identiques" : "différents");
  Serial.print("leMeme versus lengths ==> "); Serial.println(compare(leMeme, lengths) ? "identiques" : "différents");
}

void loop() {}

je vais poster la méthode entière qui ne dépend pas d'autre chose, l'erreur est uniquement dans cette méthode.

static const int ESP8266_OK = 1;
static const int ESP8266_READY = 2;
static const int ESP8266_FAIL = 3;
static const int ESP8266_NOCHANGE = 4;
static const int ESP8266_LINKED = 5;
static const int ESP8266_UNLINK = 6;
static const int ESP8266_ERROR = 7;
static const int ESP8266_CONNECT = 8;
static const int ESP8266_CONNECTED = 9;
static const int ESP8266_CLOSED = 10;

int _esp8266_waitResponse(uint24_t time_out)
{
    uint24_t startime = 0;					
	ticker = 0;
				
    int so_far[10] = {0,0,0,0,0,0,0,0,0,0};
    int lengths[10] = {2,5,4,9,6,6,5,7,9,6};
    char *strings[10] = {"OK", "ready", "FAIL", "no change", "Linked", "Unlink", "ERROR", "CONNECT", "CONNECTED", "CLOSED"};
    int responses[10] = {ESP8266_OK, ESP8266_READY, ESP8266_FAIL, ESP8266_NOCHANGE, ESP8266_LINKED, ESP8266_UNLINK, ESP8266_ERROR, 
                            ESP8266_CONNECT, ESP8266_CONNECTED, ESP8266_CLOSED };
    char received;
    int response = 0;
    bool continue_loop = true;
    uint8_t j = 0;

    timer0_begin(4608, 4);		
	startime = ticker;
    while (continue_loop )
    {
        if(uart1_kbhit())
        {
            received = (char)_esp8266_getch();                       
            for (uint8_t i = 0; i < 10; i++)
            {                      
                do {
                    if ((strings[i][so_far[j]]) == received) 
                    {
                        so_far[i]++;                       
                        if (so_far[i] == lengths[i]) {
                            response = responses[i];
                            continue_loop = false;                             
                            //printf("string: %s so_far: %d response: %d ele str: %d\r\n", strings[i], so_far[i], response, i);
                            printf("resp: %d %s\r\n", response,strings[response-1]);
                            timer0_end();
                            return response;                                                  
                        }
                        j++; 
                    } else {
                        so_far[i] = 0;                       
                        break;
                    }  

                    if(uart1_kbhit()) {
                        received = (char)_esp8266_getch();                        
                    }                    
                } while(strings[i][so_far[j]] != 0);

                j = 0; 
                if(uart1_kbhit()) {
                    received = (char)_esp8266_getch();  
                }                           
            }            
        } 
        if (((ticker - startime) > time_out)) break;
    }
    timer0_end();
    return response;
}

si je comprends bien le besoin vous écouter un port série sur lequel vous recevez un flux de caractères
vous voulez identifier si un mot clé connu (dans une liste) arrive dans un certain délai

est-ce que le mot clé peut-être n'importe ou dans le flux par exemple si vous recevez dans le flux "coucouOK", est-ce que "OK" doit être reconnu ou est-ce que le flux doit être exact et donc juste "OK" pour que vous retourniez 0 (l'index de OK dans la liste) ?

dans AT command, la réponse est soit un code OK\r\n, ERROR\r\n ou FAIL\r\n et d'autres.

si je ne me trompe pas. si j'envoi
AT\r\n

je recois:
OK\r\n

il y a des commandes qui me renvoi des infos, par exemple le numéro de version:
si j'envoi:
AT+GMR\r\n

je recois des infos sur plusieurs lignes et à la dernière ligne j'a le résultat, soit Ok ou ERROR ou FAIL, ...:

Version AT 2.2.1\r\n
infos etc \r\n
OK\r\n

j'ai précisé le \r\n pour dire que c'est un retour à la ligne.
le \r\n est important pour envoyer la commande, au niveau de la réponse, soit je test OK ou OK\r\n

mais dans tous les cas, si je recoit plusieurs caractères, je doit testé chaque caractère jusqu'au OK (reponse finale), et c'est la je crois mon problème, d'apres le code, il doit y avoir une erreur.

J'ai résolu mon problème avec ce code, il fonctionne bien et sans erreur.

int _esp8266_getResponse(uint24_t timeout, bool show)
 {
    char result[1024+1];   
    uint24_t startime = 0;					
	ticker = 0;    
    uint8_t received;
    int counter = 0;
    char *p = NULL;

    memset(result, 0, 1024+1);

    timer0_begin(4608, 4);		
	startime = ticker;
    while(true) {
        if(uart1_kbhit())
		{
            received = _esp8266_getch();                            
            memcpy(result+counter, &received, 1);      
            counter++;
            memcpy(result+counter, "\0", 1);                                                        
        }
        if(((ticker - startime) > timeout)) break;
    }    
    timer0_end();
    if(show) {
        printf("\r\n%s\r\n", result);
    }

    if ((p = strstr(result, "OK")) != NULL)
        return ESP8266_OK;
    else if ((p = strstr(result, "ready")) != NULL)
        return ESP8266_READY;
    else if ((p = strstr(result, "FAIL")) != NULL)
        return ESP8266_FAIL;
    else if ((p = strstr(result, "ERROR")) != NULL)
        return ESP8266_ERROR;
    else if ((p = strstr(result, "no change")) != NULL)
        return ESP8266_NOCHANGE;
    else if ((p = strstr(result, "Linked")) != NULL)
        return ESP8266_LINKED;
    else if ((p = strstr(result, "Unlink")) != NULL)
        return ESP8266_UNLINK;
    else if ((p = strstr(result, "CONNECT")) != NULL)
        return ESP8266_CONNECT;
    else if ((p = strstr(result, "CONNECTED")) != NULL)
        return ESP8266_CONNECTED;
     else if ((p = strstr(result, "CLOSED")) != NULL)
        return ESP8266_CLOSED;

    return 0;
}

Euh c’est de l’obfuscation volontaire? :roll_eyes:

Pourquoi ne pas faire tout simplement

if (uart1_kbhit()) {
  result[counter++] = esp8266_getch();      
  result[counter] = '\0';                                   
}

Result est très grand sur la pile, attention à la mémoire… de combien avez vous vraiment besoin ? La lobngueur du plus grand mot clé plus un et vous faites un buffer circulaire (a moins que vous ne vouliez toute la réponse)

oui en effet je peux faire comme ceci, car dans une autre méthode je pouvais avoir des données binaires, le 0 ne servira à rien, dans ce cas ci ce n'est que du caractères.
j'ai réservé 1024 au cas ou mais je ne pense pas que j'arriverais jusque là, je la descendrai à 256 ou 512.
Dans une autre fonction j'ai mis 203800 (200ko) , car j'avais un fichier en moyenne de 178ko, au niveau mémoire c'est bon, jusque 512ko.

[EDIT]
ici j'ai besoin de memcpy, car je recoit aussi des données binaires. c'est dans une autre fonction ou j'utilise memcpy alors que je n'ai pas besoin.

Merci pour la simplification de l'affectation de

result[counter++] = esp8266_getch(); 

je n'y avais pas pensé.

Memcpy pour copier 1 octet c’est le marteau pour écraser une mouche…. Une simple affectation fonctionne pour n’importe quel type de données - vous copiez un octet, que ce soit de l’ASCII à ou autre chose.

En revanche vous ne pouvez pas utiliser strcmp() pour comparer du binaire et il faut un zéro à la fin du texte mais memcmp() dans le cas du binaire.

Concernant la taille du buffer n’oubliez pas de tester le débordement que ce soit 256 512 ou 1024 et préférez un buffer global plutôt qu’un alloué sur la pile, se sera plus robuste (sur ESP32 la pile à une taille fixée par exemple).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.