Relazione tra stringa e valore

salve a tutti,

da una connessione can, con questo aggeggio(max232, AOZ1282CI)
e con questo codice:

/*
   Description:
   Use ATOM CAN to send and receive information,
   delete the macro definition `CAN_SENDER` to compile the receiving part
   of the program,
   and enable the macro definition `CAN_SENDER` to compile the sending part of
   the program.
   You need to use two ATOM CANs for testing
*/


#include "M5Atom.h"
#include "ESP32CAN.h"
#include "CAN_config.h"

boolean newData = false;
const byte numBytes = 8;
byte receivedBytes[numBytes];
byte numReceived = 0;
bool unit;
int  inc;
int  ft;
int  cm;
int  distanza;
//int mask = 268435710; // hex 0x100000FE
int mask = 282067198; // hex 0x10D000FE dovrebbe essere la misura...


#define CAN_UNIT
//#define CAN_SENDER

#define CAN_MSG_ID      0x001

CAN_device_t CAN_cfg;             // CAN Config
unsigned long previousMillis = 0; // will store last time a CAN Message was send
const int   interval = 80;        // interval at which send CAN Messages (milliseconds)
const int   rx_queue_size = 10;     // Receive Queue size
int         LedNumberCount = 0;
int         waitCANData = 0;

uint8_t     msgcnt = 0;

void setup()
{
  M5.begin(true, true, true);
  Serial.println("Atom Install OK....");
  M5.dis.fillpix(CRGB(0, 100, 0));

  CAN_cfg.speed = CAN_SPEED_1000KBPS;

  //CAN_cfg.tx_pin_id = GPIO_NUM_26;
  //CAN_cfg.rx_pin_id = GPIO_NUM_32;

  CAN_cfg.tx_pin_id = GPIO_NUM_22;
  CAN_cfg.rx_pin_id = GPIO_NUM_19;
  CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));

  ESP32Can.CANInit();
  Serial.println("CAN Install");
  M5.dis.fillpix(CRGB(100, 0, 0));
}



void loop()
{
  unsigned long currentMillis = millis();

#ifndef CAN_SENDER
  // Send CAN Message
  CAN_frame_t rx_frame;

  if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
  {

    if (rx_frame.FIR.B.FF == CAN_frame_std)
    {
      Serial.printf("New standard frame");
    }
    else
    {
      Serial.printf("New extended frame");
    }

    if (rx_frame.FIR.B.RTR == CAN_RTR)
    {
      Serial.printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC);
    }
    else
    {
      Serial.printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC);
      for (int i = 0; i < rx_frame.FIR.B.DLC; i++)
      {
        Serial.printf("0x%02X ", rx_frame.data.u8[i]);
        //        if ( rx_frame.MsgID == mask) {
        //          Serial.printf("0x%02X ", rx_frame.data.u8[i]);
        //        }
      }

      //      //////////////////////////////////////////////////////////


      Serial.printf("\n");

      if ( rx_frame.data.u8[0] == 0x01 )
      {
        CAN_frame_t tx_frame;
        tx_frame.FIR.B.FF = CAN_frame_std;
        tx_frame.MsgID = CAN_MSG_ID;
        tx_frame.FIR.B.DLC = 8;
        tx_frame.data.u8[0] = 0x02;
        tx_frame.data.u8[1] = rx_frame.data.u8[1];
        tx_frame.data.u8[2] = 0x00;
        tx_frame.data.u8[3] = 0x00;
        tx_frame.data.u8[4] = 0x00;
        tx_frame.data.u8[5] = 0x00;
        tx_frame.data.u8[6] = 0x00;
        tx_frame.data.u8[7] = 0x00;
        ESP32Can.CANWriteFrame(&tx_frame);
      }
    }
  }
#else

  if (currentMillis - previousMillis >= interval)
  {
    //ESP32Can.CANInit();
    previousMillis = currentMillis;
    CAN_frame_t tx_frame;
    tx_frame.FIR.B.FF = CAN_frame_std;
    tx_frame.MsgID = CAN_MSG_ID;
    tx_frame.FIR.B.DLC = 8;
    tx_frame.data.u8[0] = 0x01;
    tx_frame.data.u8[1] = msgcnt;
    tx_frame.data.u8[2] = 0x00;
    tx_frame.data.u8[3] = 0x00;
    tx_frame.data.u8[4] = 0x00;
    tx_frame.data.u8[5] = 0x00;
    tx_frame.data.u8[6] = 0x00;
    tx_frame.data.u8[7] = 0x00;

    ESP32Can.CANWriteFrame(&tx_frame);
    //ESP32Can.CANStop();
    msgcnt ++;
    if ( msgcnt > 29 )
    {
      msgcnt = 0;
    }

  }

  CAN_frame_t rx_frame;

  if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
  {

    if (rx_frame.FIR.B.FF == CAN_frame_std)
    {
      Serial.printf("New standard frame");
    }
    else
    {
      Serial.printf("New extended frame");
    }

    if (rx_frame.FIR.B.RTR == CAN_RTR)
    {
      Serial.printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC);

   
    }
    else
    {
      Serial.printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC);
      for (int i = 0; i < rx_frame.FIR.B.DLC; i++)
      {
        Serial.printf("0x%02X ", rx_frame.data.u8[i]);
    
      }
      Serial.printf("\n");

      if ( rx_frame.data.u8[0] == 0x02)
      {
        if ( rx_frame.data.u8[1] < 25 )
        {
          M5.dis.drawpix( rx_frame.data.u8[1], CRGB(100, 0, 0));


        }
        else if ( rx_frame.data.u8[1] > 27 )
        {
          M5.dis.fillpix(CRGB(0, 0, 20));
        }
        waitCANData = 0;
      }
    }
  }

#endif
  //waitCANData
  M5.update();
  if (M5.Btn.isPressed())
  {
    M5.dis.clear();
    esp_restart();
  }
  delay(10);
}

ottengo un output del genere:

New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40
New extended frame from 0x100000FE, DLC 8, Data 0x00 0x02 0x00 0x80 0x00 0x8F 0x21 0x0C 
New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40
New extended frame from 0x10C600FE, DLC 8, Data 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40 
New extended frame from 0x10C100FE, DLC 8, Data 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40  
New extended frame from 0x10C500FE, DLC 1, Data 0x00

ora sto cercando di capire a cosa corrispondono quegli "header"
sono riuscito a filtrarne uno che credo mi interessi (quello con il dato da 4 byte) ed ora sto cercando di ricalcolare il valore della stringa.

ho provato a sommarli a due e due, i primi tre, gli ultimi tre etc etc ma non riesco a comprendere....

ho associato l'output CAN a quello del display dell'apparecchio ed ho stilato una tabella:

00 00 80 3f -------- 100
ae 47 81 3f -------- 101
5c 8f 82 3f -------- 102
0a d7 83 3f -------- 103
d8 1e 85 3f -------- 104
66 66 86 3f -------- 105

ed ancora

81 95 63 3f -------- 2 11
1b 2f 5d 3f -------- 2 10
48 e1 86 40 -------18 9
12 83 b8 40 -------1811

non riesco a trovare una relazione ......

qualche idea?

Non ho esperienza con il CANBUS (anche se avevo un progettino per il mio scooter, per ora accantonato) quindi seguo, ma intanto di segnalo che dovresti modificare il post per chiudere il blocco "code" prima di "ora sto cercando di capire" altrimenti tutti i tuoi commenti finiscono formattati con il codice e quindi senza interruzioni di linea automatici.. :wink:

sto provando le varie combinazioni con questo sistema....

          byte a = rx_frame.data.u8[4];
          byte b = rx_frame.data.u8[3];
          byte c = rx_frame.data.u8[2];
          byte d = rx_frame.data.u8[1];

          piedi = d;          // riceve byte basso
          piedi += (int)c << 8; // riceve byte alto

ma senza apparente successo...

Non essendoci per quanto ne so uno "standard" per i messaggi inviati via CANBUS temo che cercare di "dedurli" sniffando cosa si riceve non sia propriamente facile. Nel tuo caso ad esempio se i byte 1 e 2 sai che sono un valore intero bisogna capire la codifica ossia se con o senza segno, se sono big-endian , little-endian o middle-endian.
La cosa migliore è cercare di trovare in rete informazioni sulla comunicazione di quello specifico apparato (cos'è?) e da lì cercare di identificare i messaggi che ti interessano.

Occhio che gli array in C partono da zero, non da uno, quindi nel codice che hai postato stai leggendo 4 byte dal secondo al quinto, che non credo sia quello che vuoi.

Ciao, Ale.

Vero, ma non sapendo noi come sia fatto il messaggio CAN, non è detto, ci sono messaggi da 4 byte ed anche da 8, così come da 1 e, come dicevo, non sappiamo (ma temo non lo sappia neanche l'OP) a cosa debbano corrispondere quei byte se ad un intero un long, con o senza segno, quale codifica endian, eccetera...

Ecco, puoi spiegare meglio come hai fatto questa associazione? Magari, oltre a spiegarci quale apparato ti sta mandando quei dati (un'auto? Uno scooter? Cosa? Ed esattamente quale modello?) mostrando anche i corrispondenti output?

Grazie !!

Cerco di spiegare un po’:
Un misuratore di distanze ad ultrasuoni con display, é collegato serialmente ad uno scatolo che converte la seriale in CAN. Nel mio primo post ho allegato l’output dei messaggi can che ricevo in uscita dallo scatolo sul serial monitor.. quando leggo la seriale in uscita dal misuratore ho un output tipo:
(post relativo)

  |0  60
  |1  93
  |0  60
  |1  95
  |0  70
  |1 211
  |0  70
  |1 208
  |0  70
  |1 207

l'associazione è stata fatta tra il dato sul display del misuratore e la stringa can letta sul monitor seriale con lo sketch del primo post..

il misuratore puo visualizzare/inviare il dato sulla distanza sia in cm che in piedi/pollici

qui sta visualizzando/inviando in cm:
|0 60
|1 93

qui in imperiale:
|0 70
|1 211

lo scatolo serve a far comunicare il misuratore con il resto del network... per cominciare vorrei interpretare il dato sulla distanza (visto che conosco l'informazione seriale) e poi chissà essere in grado di decodificare anche gli altri dati che girano per il CAN

Ok, iniziamo da qui. Quello che mostri è l'output diretto dalla seriale del sensore, mostrato come caratteri. quindi di fatto sembra composto sempre da 8 caratteri: il "pipe" (sicuro?), un carattere 0 o 1, uno spazio, tre caratteri che indicano la distanza, e poi un fine riga (i due caratteri CR ed LF, ossia ASCII 13 e 10). Ma se mandi sempre 8 caratteri, mi chiedo io, perché nell'output dei messaggi CAN che hai mostrato ce ne sono alcuni con il payload da 1 solo byte, altri da 4, oltre a quelli da 8 byte?
In secondo luogo, non conoscendo come quello "scatolo" converta i dati, per prima cosa direi che dovresti mostrarci i valori dei byte che ricevi dal sensore ossia un piccolo sketch come quello che hai usato ma che invece di scrivere il carattere ne fa print in esadecimale:

void setup() {

  M5.begin();

  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, 21, 22);

  pinMode(5, OUTPUT);
  digitalWrite(5, 1);
}


void loop() {

  if (Serial2.available()) {
    byte ch = Serial2.read();
    Serial.print(ch, HEX); Serial.print(" ");
    if (ch == '\n')
      Serial.println();
  }
}

quindi riporta questo output e proviamo a fare "scopa".
Per quanto riguarda lo "scatolo" poi, tu hai dato un link ad un "coso" che non mi sembra affatto sia un CANBUS, ma parlano solo di "LBUS"! Quindi temo che forse ti convenga studiare un poco come funzioni questo LBUS (ad esempio iniziando da QUI o QUI) prima di avventurarti a cercare di decodificare i singoli byte. Magari è più semplice del previsto.. :wink:

i messaggi can con payload da 1 e da 8 credo siano altre cose che ancora non ho capito... non cambiano mai .... quello che cambia, se il sensore di distanza misura cose diverse, è quello da 4

Si ma quello che ci hai fatto vedere sono 8 byte, come dicevo, per cui non credo che si "perda" 4 byte o che faccia una sua "ricodifica" in qualche modo.
Ed in ogni caso, ripeto, quell'aggeggio non parla CANBUS ma quell'LBUS che non conosco affatto (e penso neanche tu...) quindi temo che oltre alla prova che ti ho indicato (per avere la certezza dei valori esadecimali dei byte che riceve dalla seriale) dovrai anche studiardi il protocollo LBUS.

Quando il misuratore misura cose che si muovono, l’unica stringa CAN che cambia é quella from 0x10D000FE che é di 4 byte!!
sono quasi sicuro che sia CAN perché il pinout del connettore parla di canL e canH Qui

con arduino collegato alla rs232 del misuratore e questo sketch

void setup() {

  M5.begin();

  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, 21, 22);

  pinMode(5, OUTPUT);
  digitalWrite(5, 1);
}


void loop() {

  if (Serial2.available()) {
    byte ch = Serial2.read();
    Serial.print(ch, HEX); Serial.print(" ");
    if (ch == '\n')
      Serial.println();
  }
}

ed il misuratore che sta misurando 100 cm (come dice il suo display), questo è l'output

7C 31 20 31 30 30 D A 

101

7C 31 20 31 30 31 D A

102

7C 31 20 31 30 32 D A

200

7C 31 20 32 30 30 D A

con il misuratore che misura in imperiale
3 3

7C 31 20 33 30 33 D A 

1310

7C 31 31 33 31 30 D A

scopa?

È praticamente testo piano in ASCII

trovi una relazione con i messaggi CAN?

Guarda qua

se paragono la stringa seriale a quella CAN quando il misuratore sta misurando 100 cm:
seriale = 7C 31 20 31 30 30 D A
CAN = 00 00 80 3f

i primi due byte della seriale mi dicono che stiamo parlando di cm
i seguenti 4 contengono la misura
e gli ultimi due per chiudere la stringa

il payload del CAN è di 4 byte ma a parità di distanza misurata sono diversi da quelli trasportati via seriale.....

qualcuno ci trova una relazione?

Se misuri la stessa distanza (100 cm) con la lettura seriale ottieni 2 risultati diversi per il metrico e l'imperiale, ma il dato del CAN cambia o rimane lo stesso?

Ciao, Ale.

cambia!!

per i 100 cm è 00 00 80 3f
per i 3 3 ft è 2d b2 7d 3f

Esatto, quindi quello che ricevi da seriale è esattamente quella stringa con quel formato che ho indicato nel post #9, e confermo che i terminatori di riga ci sono entrambi.
Fin qui tutto ok e chiaro quindi.

Purtroppo per te, no.
Allo stato attuale non vedo alcuna logica, ossia in che modo quel modulo "riconverta" l'uscita seriale perché, appunto, 8 byte (ma anche ignorando i CR LF sarebbero 6) possano diventare 4, tra l'altro con la trascodifica che hai riportato sembra che i 4 byte del BUS finiscano sempre con il 3F (che tra l'altro in ASCII è un punto interrogativo) ma non ha per me alcun senso questa tabella di correlazione che hai postato all'inizio, così come quei "from" (che sono poi degli ID di messaggio se non ricordo male).

Si ma è probabile, anzi direi sicuro, che questo LBUS lo abbiano implementato "fisicamente" su CANBUS ma questo non basta. Se vuoi poter comunicare con Arduino temo che non ci sia per te altra scelta che cercare di approfondire quel convertitore che tipo di conversione faccia in realtà e soprattutto come funzionano i messaggi LBUS (ossia come sono strutturati e come sono veicolati tramite CANBUS). Ad esempio il fatto che tu abbi dei MsgID non solo per te sconoscuti ma anche apparentemente "variabili" mi dà l'idea che la codifica che ti interessa non segua esattamente la struttura che ti aspetti di trovare analizzandoli come se fossero CANBUS.

In ogni caso l'unica cosa che per ora mi sento di consigliarti è di provare a collegare SOLO Arduino al CUB-1 (che a sua volta è connesso via seriale a UDM-1), lasciare attivo il dump sulla seriale di Arduino di ciò che riceve via CANBUS/LBUS con un ostacolo ad esattamente 100 cm e vedere quali messaggi passano sul bus per almeno una decina di secondi. Poi posta nuovamente qui l'output seriale di Arduino e vediamo che riusciamo a dedurne.

Ma se non dovesse funzionare, allora temo che dovresti attivarti tu per cercare di ottenere più informazioni tecniche possibili su LBUS, magari dal produttore stesso.

EDIT: scusa, ma ripensandoci bene, ma rispetto a questo output:

New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40
New extended frame from 0x100000FE, DLC 8, Data 0x00 0x02 0x00 0x80 0x00 0x8F 0x21 0x0C 
New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40
New extended frame from 0x10C600FE, DLC 8, Data 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40 
New extended frame from 0x10C100FE, DLC 8, Data 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
New extended frame from 0x10D000FE, DLC 4, Data 0x12 0x83 0xB8 0x40  
New extended frame from 0x10C500FE, DLC 1, Data 0x00

non vedo dove si trovino le sequenze che hai indicato e che avresti identificato ossia:

00 00 80 3f -------- 100
ae 47 81 3f -------- 101
5c 8f 82 3f -------- 102
0a d7 83 3f -------- 103
d8 1e 85 3f -------- 104
66 66 86 3f -------- 105

Come le hai ottenute/ricavate?