ESP32 S2 mini Lolin / Wemos definition pin RX / TX pour lecture de canbus de voiture

Type de processeur

esp32s2

Description de la carte de développement

esp32 - s2 mini / LOLIN S2 MINI

Configuration matérielle

Port USB natif branché sur l'ordinateur

Nom de l'IDE

Arduino IDE

Version

v1.8.18

Système opérateur

Windows 10

Bibliothèques utilisées

esp32 by Espressif systems version 2.0.8

Description

Bonjour
Je cherche à récupérer les informations du canbus confort en 125kbit d'une voiture à l'aide d'un ESP32 LOLIN S2 MINI.

Voici ce que j'ai déjà fait :

  • j'ai réussi à lire les données de la voiture et à trouver le bon id de frame de canbus que je devrais utiliser dans mon code. Mais le problème est que j'ai réussi cela avec une carte CANBed de Seeed Studio – Kit de développement de bus CAN pour Arduino (ATmega32U4 avec MCP2515 et MCP2551)
  • Cette carte est sur une base de ATmega32U4 avec le bootloader Arduino Leonardo couplée à un Contrôleur de bus CAN MCP2515 et émetteur-récepteur de bus CAN MCP2551
  • J'ai utilisé ce code pour récupérer les informations de la climatisation dont j'avais besoin et cela fonctionne parfaitement
/////////////////////
//    Libraries    //
/////////////////////
#include <SPI.h>
#include <Wire.h>

#include <mcp2515.h> // https://github.com/autowp/arduino-mcp2515 + https://github.com/watterott/Arduino-Libs/tree/master/digitalWriteFast

/////////////////////
//  Configuration  //
/////////////////////

#define CS_PIN_CAN0 17

#define SERIAL_SPEED 115200
#define CAN_SPEED CAN_125KBPS // Entertainment CAN bus - Low speed
#define CAN_FREQ MCP_16MHZ // Switch to 8MHZ if you have a 8Mhz module

////////////////////
// Initialization //
////////////////////

MCP2515 CAN0(CS_PIN_CAN0); // CAN-BUS Shield N°1

////////////////////
//   Variables    //
////////////////////


String LeftTemp;
String RightTemp;

// CAN-BUS Messages
struct can_frame canMsgRcv;

void setup() {

    // Initalize Serial for debug
    Serial.begin(SERIAL_SPEED);

    // CAN-BUS from car
    Serial.print("Initialization CAN0");
    
  CAN0.reset();
  CAN0.setBitrate(CAN_SPEED, CAN_FREQ);
  while (CAN0.setNormalMode() != MCP2515::ERROR_OK) {
    delay(100);
  }
}

void loop() {

  // Receive CAN messages from the car
  if (CAN0.readMessage( & canMsgRcv) == MCP2515::ERROR_OK) {
    int id = canMsgRcv.can_id;
    int len = canMsgRcv.can_dlc;

    if (id == 464){

     char tmp[3];

        snprintf(tmp, 3, "%02X", canMsgRcv.data[5]);
        LeftTemp = String (tmp);
        Serial.print("LeftTemp = ");  
        Serial.println(LeftTemp);
        Serial.println(tmp);       

        snprintf(tmp, 3, "%02X", canMsgRcv.data[6]);       
        RightTemp = String (tmp);
        Serial.print("RightTemp = ");        
        Serial.println(RightTemp);
        Serial.println(tmp);    

       Serial.println();
    }

   } 
}
  • Je précise que ce code est une adaptation et simplification d'un code récupéré sur internet. Je ne m'en octroie nullement la propriété.

Venons en désormais au pourquoi du passage en ESP32 :

  • Pour des raisons de disponibilité de taille mémoire et de rapidité de traitement de travail (même si dans ce projet cela n'était pas forcement nécessaire) je suis donc parti sur une solution d'ESP32 qui propose des cartes avec 4Mo de mémoire voir plus pour une taille assez réduite
  • Voici pourquoi j'ai choisi un ESP32-S2 mini car j'ai des animations en .gif à faire tourner dans mon projet
  • Cette partie est OK avec l'ESP32-S2
  • Il ne me reste plus qu'à récupérer le signal de can bus précédemment évoqué et tester, avec succès, avec la carte Léonardo
  • Et c'est là que les choses se compliquent. Afin de récupérer le signal canbus avec un ESP32, il est conseillé d'utiliser un trancreicever du type SN65HVD230 Can Board Connecting MCUs à mettre au niveau des broches TX et RX de la carte
  • J'avais trouvé cela sur ce site : Démo 31 : Comment utiliser l'interface CAN Arduino ESP32
  • J'ai donc acheté les composants nécessaires et réalisé ce montage :
  • J'ai ensuite charger le code pour ESP32 qui permet de traiter le signal canbus renommé TWAI
/* ESP32 TWAI receive example.
  Receive messages and sends them over serial.

  Connect a CAN bus transceiver to the RX/TX pins.
  For example: SN65HVD230

  TWAI_MODE_LISTEN_ONLY is used so that the TWAI controller will not influence the bus.

  The API gives other possible speeds and alerts:
  https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/twai.html

  Example output from a can bus message:
  -> Message received
  -> Message is in Standard Format
  -> ID: 604
  -> Byte: 0 = 00, 1 = 0f, 2 = 13, 3 = 02, 4 = 00, 5 = 00, 6 = 08, 7 = 00

  Example output with alerts:
  -> Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.
  -> Bus error count: 171
  -> Alert: The RX queue is full causing a received frame to be lost.
  -> RX buffered: 4  RX missed: 46 RX overrun 0

  created 05-11-2022 by Stephan Martin (designer2k2)
*/

#include "driver/twai.h"

// Pins used to connect to CAN bus transceiver:
#define RX_PIN 37
#define TX_PIN 39

// Intervall:
#define POLLING_RATE_MS 1000

static bool driver_installed = false;

void setup() {
  // Start Serial:
  delay (5000);
  Serial.begin(115200);

  // Initialize configuration structures using macro initializers
  twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_LISTEN_ONLY);
  twai_timing_config_t t_config = TWAI_TIMING_CONFIG_125KBITS();  //Look in the api-reference for other speed sets.
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

  // Install TWAI driver
  if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
    Serial.println("Driver installed");
  } else {
    Serial.println("Failed to install driver");
    return;
  }

  // Start TWAI driver
  if (twai_start() == ESP_OK) {
    Serial.println("Driver started");
  } else {
    Serial.println("Failed to start driver");
    return;
  }

  // Reconfigure alerts to detect frame receive, Bus-Off error and RX queue full states
  uint32_t alerts_to_enable = TWAI_ALERT_RX_DATA | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL;
  if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) {
    Serial.println("CAN Alerts reconfigured");
  } else {
    Serial.println("Failed to reconfigure alerts");
    return;
  }

  // TWAI driver is now successfully installed and started
  driver_installed = true;
}

static void handle_rx_message(twai_message_t& message) {
  // Process received message
  if (message.extd) {
    Serial.println("Message is in Extended Format");
  } else {
    Serial.println("Message is in Standard Format");
  }
  Serial.printf("ID: %x\nByte:", message.identifier);
  if (!(message.rtr)) {
    for (int i = 0; i < message.data_length_code; i++) {
      Serial.printf(" %d = %02x,", i, message.data[i]);
    }
    Serial.println("");
  }
}

void loop() {
  if (!driver_installed) {
    // Driver not installed
    delay(1000);
    return;
  }
  // Check if alert happened
  uint32_t alerts_triggered;
  twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(POLLING_RATE_MS));
  twai_status_info_t twaistatus;
  twai_get_status_info(&twaistatus);

  // Handle alerts
  if (alerts_triggered & TWAI_ALERT_ERR_PASS) {
    Serial.println("Alert: TWAI controller has become error passive.");
  }
  if (alerts_triggered & TWAI_ALERT_BUS_ERROR) {
    Serial.println("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.");
    Serial.printf("Bus error count: %d\n", twaistatus.bus_error_count);
  }
  if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) {
    Serial.println("Alert: The RX queue is full causing a received frame to be lost.");
    Serial.printf("RX buffered: %d\t", twaistatus.msgs_to_rx);
    Serial.printf("RX missed: %d\t", twaistatus.rx_missed_count);
    Serial.printf("RX overrun %d\n", twaistatus.rx_overrun_count);
  }

  // Check if message is received
  if (alerts_triggered & TWAI_ALERT_RX_DATA) {
    // One or more messages received. Handle all.
    twai_message_t message;
    while (twai_receive(&message, 0) == ESP_OK) {
      handle_rx_message(message);
    }
  }
}
  • Cela n'a évidemment pas fonctionné
  • En mettant un delay de 5000 ms en début du void setup() j'ai bien les messages d'initialisations qui remontent correctement :
    --- Driver installed
    --- Driver started
    --- CAN Alerts reconfigured
  • Mais je n'ai que ça et parfois le message d'erreur "Alert: The RX queue is full causing a received frame to be lost." lorsque je déconnecte et reconnecte les fils du bus can
  • J'en ai donc déduit que les pins TX et RX étaient mal configurés

Venons en désormais à la problématique :

  • l'opération qui semblait simple s'est avéré être un casse tête. Mais où sont les PIN RX et TX sur une carte LOLIN S2 mini?
  • Et bien la réponse est qu'il n'y en a pas. Enfin il n'y en a pas en natif. Mais ce que j'ai découvert c'est qu'il est possible d'adresser les pins TX et RX à n'importe quel GPIO des cartes ESP32
    Comment utiliser avec esp32S2 l'affichage sur port série? - #21 by al1fch
  • Et bien devinez quoi. J'ai essayé plein de choses et je n'arrive pas à avoir de retour dans la console série en faisant des simples tests afin de savoir si les pins sont bien attribués
  • Voici ce que j'ai testé et qui devrait me renvoyer des informations dans la console
#include <Arduino.h>

// There are two ways to make this sketch work:
// By physically connecting the pins 4 and 5 and then create a physical UART loopback,
// Or by using the internal IO_MUX to connect the TX signal to the RX pin, creating the
// same loopback internally.
#define USE_INTERNAL_PIN_LOOPBACK 0   // 1 uses the internal loopback, 0 for wiring pins 4 and 5 externally

#define DATA_SIZE 26    // 26 bytes is a lower than RX FIFO size (127 bytes) 
#define BAUD 115200       // Any baudrate from 300 to 115200
#define TEST_UART 1     // Serial1 will be used for the loopback testing with different RX FIFO FULL values
#define RXPIN 37         // GPIO 4 => RX for Serial1
#define TXPIN 39         // GPIO 5 => TX for Serial1

uint8_t fifoFullTestCases[] = {120, 20, 5, 1};
// volatile declaration will avoid any compiler optimization when reading variable values
volatile size_t sent_bytes = 0, received_bytes = 0;


void onReceiveFunction(void) {
  // This is a callback function that will be activated on UART RX events
  size_t available = Serial1.available();
  received_bytes += available;
  Serial.printf("onReceive Callback:: There are %d bytes available: ", available);
  while (available --) {
    Serial.print((char)Serial1.read());
  }
  Serial.println();
}

void setup() {
  // UART0 will be used to log information into Serial Monitor
  Serial.begin(115200);

  // UART1 will have its RX<->TX cross connected
  // GPIO4 <--> GPIO5 using external wire
  Serial1.begin(BAUD, SERIAL_8N1, RXPIN, TXPIN); // Rx = 4, Tx = 5 will work for ESP32, S2, S3 and C3
#if USE_INTERNAL_PIN_LOOPBACK
  uart_internal_loopback(TEST_UART, RXPIN);
#endif


  for (uint8_t i = 0; i < sizeof(fifoFullTestCases); i++) {
    Serial.printf("\n\n================================\nTest Case #%d\n================================\n", i + 1);
    // onReceive callback will be called on FIFO Full and RX timeout - default behaviour
    testAndReport(fifoFullTestCases[i], false);
  }

  Serial.printf("\n\n================================\nTest Case #6\n================================\n");
  // onReceive callback will be called just on RX timeout - using onlyOnTimeout = true
  // FIFO Full parameter (5 bytes) won't matter for the execution of this test case
  // because onReceive() uses only RX Timeout to be activated
  testAndReport(5, true);
}

void loop() {
}

void testAndReport(uint8_t fifoFull, bool onlyOnTimeOut) {
  // Let's send 125 bytes from Serial1 rx<->tx and mesaure time using diferent FIFO Full configurations
  received_bytes = 0;
  sent_bytes = DATA_SIZE;  // 26 characters

  uint8_t dataSent[DATA_SIZE + 1];
  dataSent[DATA_SIZE] = '\0';  // string null terminator, for easy printing.

  // initialize all data
  for (uint8_t i = 0; i < DATA_SIZE; i++) {
    dataSent[i] = 'A' + i; // fill it with characters A..Z
  }

  Serial.printf("\nTesting onReceive for receiving %d bytes at %d baud, using RX FIFO Full = %d.\n", sent_bytes, BAUD, fifoFull);
  if (onlyOnTimeOut) {
    Serial.println("onReceive is called just on RX Timeout!");
  } else {
    Serial.println("onReceive is called on both FIFO Full and RX Timeout events.");
  }
  Serial.flush(); // wait Serial FIFO to be empty and then spend almost no time processing it
  Serial1.setRxFIFOFull(fifoFull); // testing diferent result based on FIFO Full setup
  Serial1.onReceive(onReceiveFunction, onlyOnTimeOut); // sets a RX callback function for Serial 1

  sent_bytes = Serial1.write(dataSent, DATA_SIZE); // ESP32 TX FIFO is about 128 bytes, 125 bytes will fit fine
  Serial.printf("\nSent String: %s\n", dataSent);
  while (received_bytes < sent_bytes) {
    // just wait for receiving all byte in the callback...
  }

  Serial.printf("\nIt has sent %d bytes from Serial1 TX to Serial1 RX\n", sent_bytes);
  Serial.printf("onReceive() has read a total of %d bytes\n", received_bytes);
  Serial.println("========================\nFinished!");

  Serial1.onReceive(NULL); // resets/disables the RX callback function for Serial 1
}

Ceci est le code d'exemple de la bibliothèque ESP32 de test d'émission / réception et ça ne fonctionne pas

  • Vous pouvez constater que la pin RX est définie sur 37 et la pin TX sur 39
  • J'ai bien évidemment testé aussi de définir ces pins dans le fichier C:\Users\username\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.8\variants\lolin_s2_mini\pins_arduino.h
#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <stdint.h>

// Default USB Settings
#define USB_VID 			0x303a
#define USB_PID 			0x80C2
#define USB_MANUFACTURER 	"WEMOS.CC"
#define USB_PRODUCT 		"LOLIN-S2-MINI"
#define USB_SERIAL 			"0"


// Default USB FirmwareMSC Settings
#define USB_FW_MSC_VENDOR_ID 		"ESP32-S2" 		//max 8 chars
#define USB_FW_MSC_PRODUCT_ID 		"Firmware MSC"	//max 16 chars
#define USB_FW_MSC_PRODUCT_REVISION	"1.23" 			//max 4 chars
#define USB_FW_MSC_VOLUME_NAME 		"S2-Firmware" 	//max 11 chars
#define USB_FW_MSC_SERIAL_NUMBER 	0x00000000

#define EXTERNAL_NUM_INTERRUPTS 46
#define NUM_DIGITAL_PINS        48
#define NUM_ANALOG_INPUTS       20

#define analogInputToDigitalPin(p)  (((p)<20)?(analogChannelToDigitalPin(p)):-1)
#define digitalPinToInterrupt(p)    (((p)<48)?(p):-1)
#define digitalPinHasPWM(p)         (p < 46)

static const uint8_t LED_BUILTIN = 15;
#define BUILTIN_LED  LED_BUILTIN // backward compatibility

static const uint8_t TX = 39;
static const uint8_t RX = 37;

static const uint8_t SDA = 33;
static const uint8_t SCL = 35;

static const uint8_t SS    = 12;
static const uint8_t MOSI  = 11;
static const uint8_t MISO  = 9;
static const uint8_t SCK   = 7;

static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A6 = 7;
static const uint8_t A7 = 8;
static const uint8_t A8 = 9;
static const uint8_t A9 = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A13 = 14;
static const uint8_t A14 = 15;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;
static const uint8_t A18 = 19;
static const uint8_t A19 = 20;

static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;
static const uint8_t T14 = 14;

static const uint8_t DAC1 = 17;
static const uint8_t DAC2 = 18;

#endif /* Pins_Arduino_h */

  • Pour cela j'ai réalisé le montage suivant comme définit dans le code

  • Malgré tout cela rien ne fonctionne

J'ai réalisé de multiples autres tests tous aussi infructueux que je ne vais pas détailler ici car le post commence à être long.

Je sollicite donc vos compétences afin de m'aider dans cette quête d'accomplissement de mon projet qui je le sens est proche du but.

Merci de m'avoir lu jusqu'au bout en espérant que cela puisse aussi aider d'autres personnes.

Strangistra

Bonjour @strangistra
J'ai vu que tu m'avais mentionné pour ton problème dans ta présentation. Le problème c'est que je suis en séjour dans la baie de Somme pour photographier des phoques :

Je n'ai pas internet car je suis au fin fond de la campagne en Normandie.
Du coup c'est difficile de te répondre mais malgré tout j'ai lu ton sujet en diagonale.
As tu essayé la librairie SoftwareSerial pour utiliser RX TX sans utiliser les pins 37 et 39 ?
Il me semble que j'ai utilisé les pins 1 et 2 avec SoftwareSerial sur une lolin S2 mini mais je ne les vois pas sur ton schéma :smirk:

Bonsoir @philippe86220
J'avais mentionné un des post que vous aviez traité.
Je ne vous aviez pas mentionné directement mais si vous pouvez m'aider cela serait intéressant pour la communauté.
Maintenant cela n'est pas urgent et profitez bien de votre séjour surtout pour faire des aussi jolies photos.
J'ai bien les pins 1 et 2


Elles sont sur les pins intérieurs.
Je vais tester mais sans grande espérance car il me semble avoir déjà réalisé ce montage.
Je vous remercie tout de même pour votre réponse aussi rapide.
Bonne soirée dans l'attente de vous retrouver à votre retour de séjour.

Vous savez utiliser SoftwareSerial ?
Essayez 9600 bauds
De memoire :
SoftwareSerial ss (1,2);
ss.begin(9600); // dans le setup

Pas exactement mais je vais me documenter.

Il faut mettre la pin 1 sur le TX du module et la 2 sur le RX mais ça tu l’as compris :wink:

Dans ton code quel est l’interêt de transformer une c-string en String ?
LeftTemp = String (tmp);
Mais ça concerne ta première carte et non la S2 mini donc peu importe.

Concernant le code pour ESP32, il semble que ce soit la librairie twai.h qui gère la liaison série donc SoftwareSerial.h ne te sera certainement pas d’une grande utilité.

Sans internet et sur mon IPhone c’est difficile de t’aider :wink:

Bonne journée

PS : tu devrais peut-être essayer avec une wroom 32 avec RX2 et TX2.

Bonjour @philippe86220
Merci pour ces informations.
J'ai donc fait des tests sur tes conseils et voici donc ma conclusion :

  • J'ai tester de mettre TX en pin 1 et RX en pin 2 comme tu me l'as proposé et cela a fonctionné.
  • J'ai testé cela avec le code suivant qui permet de lire dans le moniteur série le message envoyé par TX.
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 1); // RX, TX

void setup()
{
  delay (5000);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Native USB only
  }

  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
}

void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}
  • En rentrant un texte dans la console puis "ENTER", lorsque je connecte RX et TX alors j'ai bien le message qui s'affiche sur la console série.
  • Si je débranche la connexion entre RX et TX alors je n'ai rien qui remonte dans la console.
  • Conclusion, il y a bien un liaison série via TX et RX sur un ESP32-S2 Lolin min

J'ai réalisé d'autres tests en définissant maintenant en entrée TX = 39 et RX = 37 comme définit dans mon code d'origine.

  • Conclusion, cela fonctionne aussi donc les pins de liaison série TX / RX sont bien paramétrables.
  • Autre remarque constatée, visiblement la liaison série ne fonctionne pas sur les pins TX et RX si le baud dépasse 100 000. Donc avec un baud de 115 200 cela ne fonctionne pas.
  • Dernier constat, la définition des pins RX / TX dans le fichier pins_arduino.h ne change rien dans ce code. La définition des pins dans l'objet "SoftwareSerial" prévaut sur la définition des pins du fichier pins_arduino.h

Je comprends mieux certaines choses maintenant mais cela ne résout toujours pas ma problématique de lecture de Canbus.

Pour répondre à ta question, j'ai fait cela car le canbus me retourne des valeurs non numérique du type "0A, 0B, 0C, 0D, 0E, 0F" et donc j'avais besoin de conserver cette syntaxe afin de l'utiliser dans mon code. Si je ne faisait pas cela la valeur de LeftTemp retournée était la même, je ne me souvient plus laquelle.
C'est sans doute pas très propre mais c'est ce que j'ai trouvé de mieux et de plus simple pour continuer mon code.

Ta proposition d'utiliser SoftwareSerial.h m'a permis de vérifier ce que j'ai décrit en début de post. Merci pour ça.

J'espère que cela aidera d'autres personnes à mieux comprendre l'ESP32-S2.

Je vais donc continuer mes investigations afin de faire fonctionner la lecture du canbus.

Bonjour @strangistra,

Vous avez essayé la librairie emucan

// EMUCan Lib Simple Test Example

// Example to be run on ESP32
// Configure the EMU Black to send the CAN Stream at 500KBPS

// https://www.designer2k2.at
// Stephan Martin 27.12.2022


#include "EMUcan.h"
// EMU initialized with base ID 600:
EMUcan emucan(0x600);

// Needed for the CAN Interface on the ESP32 (called TWAI):
#include "driver/twai.h"

// Pins used to connect to CAN bus transceiver:
#define RX_PIN 21
#define TX_PIN 22

unsigned long previousMillis = 0;
const long interval = 500;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  Serial.print("EMUCAN_LIB_VERSION: ");
  Serial.println(EMUCAN_LIB_VERSION);

  Serial.println("------- CAN Read ----------");

  // Initialize configuration structures using macro initializers
  twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_LISTEN_ONLY);
  twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();  //Look in the api-reference for other speed sets.
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

  // Install TWAI driver
  if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
    Serial.println("Driver installed");
  } else {
    Serial.println("Failed to install driver");
  }

  // Start TWAI driver
  if (twai_start() == ESP_OK) {
    Serial.println("Driver started");
  } else {
    Serial.println("Failed to start driver");
  }

  // Reconfigure alerts to detect frame receive, Bus-Off error and RX queue full states
  uint32_t alerts_to_enable = TWAI_ALERT_RX_DATA | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL;
  if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) {
    Serial.println("CAN Alerts reconfigured");
  } else {
    Serial.println("Failed to reconfigure alerts");
  }
}

void loop() {
  // put your main code here, to run repeatedly:

  // Call the EMUcan lib with every received frame:
  uint32_t alerts_triggered;
  twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(1));
  if (alerts_triggered & TWAI_ALERT_RX_DATA) {
    // One or more messages received. Handle all.
    twai_message_t message;
    while (twai_receive(&message, 0) == ESP_OK) {
      emucan.checkEMUcan(message.identifier, message.data_length_code, message.data);
    }
  }

  // Serial out every second:
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (emucan.EMUcan_Status() == EMUcan_RECEIVED_WITHIN_LAST_SECOND) {
      Serial.print(emucan.emu_data.RPM);
      Serial.print(";");
      Serial.print(emucan.emu_data.TPS);
      Serial.print(";");
      Serial.print(emucan.emu_data.IAT);
      Serial.print(";");
      Serial.print(emucan.emu_data.MAP);
      Serial.print(";");
      Serial.println(emucan.emu_data.pulseWidth);
    } else {
      Serial.println("No communication from EMU");
    }
    if (emucan.emu_data.flags1 & emucan.F_IDLE) {
      Serial.println("Engine Idle active");
    }
    if (emucan.decodeCel()) {
      Serial.println("WARNING Engine CEL active");
    }
  }
}


TWAI

Bonne journée.

Bonjour @philippe86220

Je ne peux pas utiliser cette bibliothèque car elle scan uniquement le can bus moteur en 500Kbits alors que je cherche à scanner le can bus confort de la voiture qui tourne lui en 125Kbits.

Je sais que l'on peut changer la vitesse du can bus mais les variables retournées sont uniquement que pour le moteur donc changer la vitesse ne me donnera pas ce que je cherche.

J'ai trouvé un autre code similaire à celui que vous m'avez proposé mais ce dernier ne fonctionne toujours pas.

#include "driver/gpio.h"
#include "driver/twai.h"

//#define ACCEPT_ID                  0x036   //11 bit standard format ID;if not define any ID,accept all IDs.

#ifdef ACCEPT_ID
#define MASK_ID                  ~(0x7FF << 21)   //32 bit standard format ID,but only care for the frist 11 bits.
#define TWAI_FILTER_CONFIG() {.acceptance_code = (ACCEPT_ID << 21),.acceptance_mask = MASK_ID,.single_filter = true};
#endif

// Pins used to connect to CAN bus transceiver:
#define RX_PIN 2
#define TX_PIN 1

// Intervall:
#define POLLING_RATE_MS 10


void setup() {
  // put your setup code here, to run once:
  delay (5000);
  Serial.begin(115200);
  twai_init();
}

void loop() {
  // put your main code here, to run repeatedly:
  twai_receive();
}



void twai_init()
{
  //Initialize configuration structures using macro initializers
  twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_NORMAL);
  //twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_LISTEN_ONLY);
  twai_timing_config_t t_config = TWAI_TIMING_CONFIG_125KBITS();
#ifdef ACCEPT_ID
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG();
#else
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
#endif

  //Install TWAI driver
  if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
    Serial.println("Driver installed");
  } else {
    Serial.println("Failed to install driver");
    return;
  }

  //Start TWAI driver
  if (twai_start() == ESP_OK) {
    Serial.println("Driver started");
  } else {
    Serial.println("Failed to start driver");
    return;
  }
}

void twai_receive()
{
  //Wait for message to be received
  twai_message_t message;
  if (twai_receive(&message, pdMS_TO_TICKS(POLLING_RATE_MS)) == ESP_OK) {
    //    Serial.println("Message received");
    Serial.println("ID DATA----------->");
    Serial.print(message.identifier, HEX);
    if (!(message.rtr))
    {
      for (int i = 0; i < message.data_length_code; i++)
      {
        Serial.print(" ");
        Serial.print(message.data[i], HEX);
      }
    }
    Serial.println(" ");
  } else {
    Serial.println("Failed to receive message");
    return;
  }
}

J'ai trouvé des infos sur un problème similaire voir identique mais je ne comprends rien à ce qui est dit dans le ticket GITHub.

Je continue d'investiguer.

Bonsoir @strangistra
Avez-vous une carte wroom32 avec des pins RX2 TX2 ? À mon avis votre montage et votre code devraient fonctionner sur ce type d’ESP32.
De plus, le prix n’est pas très élevé.
Ça vaut le coup d’essayer.

PS : j’avais trouvé un bout de code qui permettait de paramétrer les pins RX et TX de la librairie twai.h mais je n’arrive plus à mettre la main dessus. D’ailleurs avez-vous le lien pour la télécharger ?

J'ai installé la bibliothèque expressif/arduino-esp32

Dans cette bibliothèque j'ai l'exemple TWAIreceive

Dans ce dossier j'ai un ensemble de fichier mais pas de twai.h
C:\Users\xxxxx\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.8\cores\esp32

Je comprends pas ou se trouve les fichiers "driver/gpio.h" et "driver/twai.h".

J'ai pensais à changer de carte mais les dimensions ne vont pas mais je vais continuer de chercher.

Bonjour @strangistra,
Apparemment tu es sous windows, la librairie twai.h se trouve ici :
C:\Users\Utilisateur\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\tools\sdk\esp32s2\include\driver\include\driver

Il en existe une pour :

  • esp32
  • esp32c3
  • esp32s2
  • esp32s3

Voici la version S2 :

/*
 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include "soc/soc_caps.h"
#if SOC_TWAI_SUPPORTED

#include "freertos/FreeRTOS.h"
#include "esp_types.h"
#include "esp_intr_alloc.h"
#include "esp_err.h"
#include "gpio.h"
#include "hal/twai_types.h"

/* -------------------- Default initializers and flags ---------------------- */
/** @cond */    //Doxy command to hide preprocessor definitions from docs
/**
 * @brief Initializer macro for general configuration structure.
 *
 * This initializer macros allows the TX GPIO, RX GPIO, and operating mode to be
 * configured. The other members of the general configuration structure are
 * assigned default values.
 */
#define TWAI_GENERAL_CONFIG_DEFAULT(tx_io_num, rx_io_num, op_mode) {.mode = op_mode, .tx_io = tx_io_num, .rx_io = rx_io_num,        \
                                                                    .clkout_io = TWAI_IO_UNUSED, .bus_off_io = TWAI_IO_UNUSED,      \
                                                                    .tx_queue_len = 5, .rx_queue_len = 5,                           \
                                                                    .alerts_enabled = TWAI_ALERT_NONE,  .clkout_divider = 0,        \
                                                                    .intr_flags = ESP_INTR_FLAG_LEVEL1}

/**
 * @brief   Alert flags
 *
 * The following flags represents the various kind of alerts available in
 * the TWAI driver. These flags can be used when configuring/reconfiguring
 * alerts, or when calling twai_read_alerts().
 *
 * @note    The TWAI_ALERT_AND_LOG flag is not an actual alert, but will configure
 *          the TWAI driver to log to UART when an enabled alert occurs.
 */
#define TWAI_ALERT_TX_IDLE                  0x00000001  /**< Alert(1): No more messages to transmit */
#define TWAI_ALERT_TX_SUCCESS               0x00000002  /**< Alert(2): The previous transmission was successful */
#define TWAI_ALERT_RX_DATA                  0x00000004  /**< Alert(4): A frame has been received and added to the RX queue */
#define TWAI_ALERT_BELOW_ERR_WARN           0x00000008  /**< Alert(8): Both error counters have dropped below error warning limit */
#define TWAI_ALERT_ERR_ACTIVE               0x00000010  /**< Alert(16): TWAI controller has become error active */
#define TWAI_ALERT_RECOVERY_IN_PROGRESS     0x00000020  /**< Alert(32): TWAI controller is undergoing bus recovery */
#define TWAI_ALERT_BUS_RECOVERED            0x00000040  /**< Alert(64): TWAI controller has successfully completed bus recovery */
#define TWAI_ALERT_ARB_LOST                 0x00000080  /**< Alert(128): The previous transmission lost arbitration */
#define TWAI_ALERT_ABOVE_ERR_WARN           0x00000100  /**< Alert(256): One of the error counters have exceeded the error warning limit */
#define TWAI_ALERT_BUS_ERROR                0x00000200  /**< Alert(512): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */
#define TWAI_ALERT_TX_FAILED                0x00000400  /**< Alert(1024): The previous transmission has failed (for single shot transmission) */
#define TWAI_ALERT_RX_QUEUE_FULL            0x00000800  /**< Alert(2048): The RX queue is full causing a frame to be lost */
#define TWAI_ALERT_ERR_PASS                 0x00001000  /**< Alert(4096): TWAI controller has become error passive */
#define TWAI_ALERT_BUS_OFF                  0x00002000  /**< Alert(8192): Bus-off condition occurred. TWAI controller can no longer influence bus */
#define TWAI_ALERT_RX_FIFO_OVERRUN          0x00004000  /**< Alert(16384): An RX FIFO overrun has occurred */
#define TWAI_ALERT_TX_RETRIED               0x00008000  /**< Alert(32768): An message transmission was cancelled and retried due to an errata workaround */
#define TWAI_ALERT_PERIPH_RESET             0x00010000  /**< Alert(65536): The TWAI controller was reset */
#define TWAI_ALERT_ALL                      0x0001FFFF  /**< Bit mask to enable all alerts during configuration */
#define TWAI_ALERT_NONE                     0x00000000  /**< Bit mask to disable all alerts during configuration */
#define TWAI_ALERT_AND_LOG                  0x00020000  /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */

/** @endcond */

#define TWAI_IO_UNUSED                   ((gpio_num_t) -1)   /**< Marks GPIO as unused in TWAI configuration */

/* ----------------------- Enum and Struct Definitions ---------------------- */

/**
 * @brief   TWAI driver states
 */
typedef enum {
    TWAI_STATE_STOPPED,             /**< Stopped state. The TWAI controller will not participate in any TWAI bus activities */
    TWAI_STATE_RUNNING,             /**< Running state. The TWAI controller can transmit and receive messages */
    TWAI_STATE_BUS_OFF,             /**< Bus-off state. The TWAI controller cannot participate in bus activities until it has recovered */
    TWAI_STATE_RECOVERING,          /**< Recovering state. The TWAI controller is undergoing bus recovery */
} twai_state_t;

/**
 * @brief   Structure for general configuration of the TWAI driver
 *
 * @note    Macro initializers are available for this structure
 */
typedef struct {
    twai_mode_t mode;               /**< Mode of TWAI controller */
    gpio_num_t tx_io;               /**< Transmit GPIO number */
    gpio_num_t rx_io;               /**< Receive GPIO number */
    gpio_num_t clkout_io;           /**< CLKOUT GPIO number (optional, set to -1 if unused) */
    gpio_num_t bus_off_io;          /**< Bus off indicator GPIO number (optional, set to -1 if unused) */
    uint32_t tx_queue_len;          /**< Number of messages TX queue can hold (set to 0 to disable TX Queue) */
    uint32_t rx_queue_len;          /**< Number of messages RX queue can hold */
    uint32_t alerts_enabled;        /**< Bit field of alerts to enable (see documentation) */
    uint32_t clkout_divider;        /**< CLKOUT divider. Can be 1 or any even number from 2 to 14 (optional, set to 0 if unused) */
    int intr_flags;                 /**< Interrupt flags to set the priority of the driver's ISR. Note that to use the ESP_INTR_FLAG_IRAM, the CONFIG_TWAI_ISR_IN_IRAM option should be enabled first. */
} twai_general_config_t;

/**
 * @brief   Structure to store status information of TWAI driver
 */
typedef struct {
    twai_state_t state;             /**< Current state of TWAI controller (Stopped/Running/Bus-Off/Recovery) */
    uint32_t msgs_to_tx;            /**< Number of messages queued for transmission or awaiting transmission completion */
    uint32_t msgs_to_rx;            /**< Number of messages in RX queue waiting to be read */
    uint32_t tx_error_counter;      /**< Current value of Transmit Error Counter */
    uint32_t rx_error_counter;      /**< Current value of Receive Error Counter */
    uint32_t tx_failed_count;       /**< Number of messages that failed transmissions */
    uint32_t rx_missed_count;       /**< Number of messages that were lost due to a full RX queue (or errata workaround if enabled) */
    uint32_t rx_overrun_count;      /**< Number of messages that were lost due to a RX FIFO overrun */
    uint32_t arb_lost_count;        /**< Number of instances arbitration was lost */
    uint32_t bus_error_count;       /**< Number of instances a bus error has occurred */
} twai_status_info_t;

/* ------------------------------ Public API -------------------------------- */

/**
 * @brief   Install TWAI driver
 *
 * This function installs the TWAI driver using three configuration structures.
 * The required memory is allocated and the TWAI driver is placed in the stopped
 * state after running this function.
 *
 * @param[in]   g_config    General configuration structure
 * @param[in]   t_config    Timing configuration structure
 * @param[in]   f_config    Filter configuration structure
 *
 * @note    Macro initializers are available for the configuration structures (see documentation)
 *
 * @note    To reinstall the TWAI driver, call twai_driver_uninstall() first
 *
 * @return
 *      - ESP_OK: Successfully installed TWAI driver
 *      - ESP_ERR_INVALID_ARG: Arguments are invalid
 *      - ESP_ERR_NO_MEM: Insufficient memory
 *      - ESP_ERR_INVALID_STATE: Driver is already installed
 */
esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config);

/**
 * @brief   Uninstall the TWAI driver
 *
 * This function uninstalls the TWAI driver, freeing the memory utilized by the
 * driver. This function can only be called when the driver is in the stopped
 * state or the bus-off state.
 *
 * @warning The application must ensure that no tasks are blocked on TX/RX
 *          queues or alerts when this function is called.
 *
 * @return
 *      - ESP_OK: Successfully uninstalled TWAI driver
 *      - ESP_ERR_INVALID_STATE: Driver is not in stopped/bus-off state, or is not installed
 */
esp_err_t twai_driver_uninstall(void);

/**
 * @brief   Start the TWAI driver
 *
 * This function starts the TWAI driver, putting the TWAI driver into the running
 * state. This allows the TWAI driver to participate in TWAI bus activities such
 * as transmitting/receiving messages. The TX and RX queue are reset in this function,
 * clearing any messages that are unread or pending transmission. This function
 * can only be called when the TWAI driver is in the stopped state.
 *
 * @return
 *      - ESP_OK: TWAI driver is now running
 *      - ESP_ERR_INVALID_STATE: Driver is not in stopped state, or is not installed
 */
esp_err_t twai_start(void);

/**
 * @brief   Stop the TWAI driver
 *
 * This function stops the TWAI driver, preventing any further message from being
 * transmitted or received until twai_start() is called. Any messages in the TX
 * queue are cleared. Any messages in the RX queue should be read by the
 * application after this function is called. This function can only be called
 * when the TWAI driver is in the running state.
 *
 * @warning A message currently being transmitted/received on the TWAI bus will
 *          be ceased immediately. This may lead to other TWAI nodes interpreting
 *          the unfinished message as an error.
 *
 * @return
 *      - ESP_OK: TWAI driver is now Stopped
 *      - ESP_ERR_INVALID_STATE: Driver is not in running state, or is not installed
 */
esp_err_t twai_stop(void);

/**
 * @brief   Transmit a TWAI message
 *
 * This function queues a TWAI message for transmission. Transmission will start
 * immediately if no other messages are queued for transmission. If the TX queue
 * is full, this function will block until more space becomes available or until
 * it times out. If the TX queue is disabled (TX queue length = 0 in configuration),
 * this function will return immediately if another message is undergoing
 * transmission. This function can only be called when the TWAI driver is in the
 * running state and cannot be called under Listen Only Mode.
 *
 * @param[in]   message         Message to transmit
 * @param[in]   ticks_to_wait   Number of FreeRTOS ticks to block on the TX queue
 *
 * @note    This function does not guarantee that the transmission is successful.
 *          The TX_SUCCESS/TX_FAILED alert can be enabled to alert the application
 *          upon the success/failure of a transmission.
 *
 * @note    The TX_IDLE alert can be used to alert the application when no other
 *          messages are awaiting transmission.
 *
 * @return
 *      - ESP_OK: Transmission successfully queued/initiated
 *      - ESP_ERR_INVALID_ARG: Arguments are invalid
 *      - ESP_ERR_TIMEOUT: Timed out waiting for space on TX queue
 *      - ESP_FAIL: TX queue is disabled and another message is currently transmitting
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not in running state, or is not installed
 *      - ESP_ERR_NOT_SUPPORTED: Listen Only Mode does not support transmissions
 */
esp_err_t twai_transmit(const twai_message_t *message, TickType_t ticks_to_wait);

/**
 * @brief   Receive a TWAI message
 *
 * This function receives a message from the RX queue. The flags field of the
 * message structure will indicate the type of message received. This function
 * will block if there are no messages in the RX queue
 *
 * @param[out]  message         Received message
 * @param[in]   ticks_to_wait   Number of FreeRTOS ticks to block on RX queue
 *
 * @warning The flags field of the received message should be checked to determine
 *          if the received message contains any data bytes.
 *
 * @return
 *      - ESP_OK: Message successfully received from RX queue
 *      - ESP_ERR_TIMEOUT: Timed out waiting for message
 *      - ESP_ERR_INVALID_ARG: Arguments are invalid
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
 */
esp_err_t twai_receive(twai_message_t *message, TickType_t ticks_to_wait);

/**
 * @brief   Read TWAI driver alerts
 *
 * This function will read the alerts raised by the TWAI driver. If no alert has
 * been issued when this function is called, this function will block until an alert
 * occurs or until it timeouts.
 *
 * @param[out]  alerts          Bit field of raised alerts (see documentation for alert flags)
 * @param[in]   ticks_to_wait   Number of FreeRTOS ticks to block for alert
 *
 * @note    Multiple alerts can be raised simultaneously. The application should
 *          check for all alerts that have been enabled.
 *
 * @return
 *      - ESP_OK: Alerts read
 *      - ESP_ERR_TIMEOUT: Timed out waiting for alerts
 *      - ESP_ERR_INVALID_ARG: Arguments are invalid
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
 */
esp_err_t twai_read_alerts(uint32_t *alerts, TickType_t ticks_to_wait);

/**
 * @brief   Reconfigure which alerts are enabled
 *
 * This function reconfigures which alerts are enabled. If there are alerts
 * which have not been read whilst reconfiguring, this function can read those
 * alerts.
 *
 * @param[in]   alerts_enabled  Bit field of alerts to enable (see documentation for alert flags)
 * @param[out]  current_alerts  Bit field of currently raised alerts. Set to NULL if unused
 *
 * @return
 *      - ESP_OK: Alerts reconfigured
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
 */
esp_err_t twai_reconfigure_alerts(uint32_t alerts_enabled, uint32_t *current_alerts);

/**
 * @brief   Start the bus recovery process
 *
 * This function initiates the bus recovery process when the TWAI driver is in
 * the bus-off state. Once initiated, the TWAI driver will enter the recovering
 * state and wait for 128 occurrences of the bus-free signal on the TWAI bus
 * before returning to the stopped state. This function will reset the TX queue,
 * clearing any messages pending transmission.
 *
 * @note    The BUS_RECOVERED alert can be enabled to alert the application when
 *          the bus recovery process completes.
 *
 * @return
 *      - ESP_OK: Bus recovery started
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not in the bus-off state, or is not installed
 */
esp_err_t twai_initiate_recovery(void);

/**
 * @brief   Get current status information of the TWAI driver
 *
 * @param[out]  status_info     Status information
 *
 * @return
 *      - ESP_OK: Status information retrieved
 *      - ESP_ERR_INVALID_ARG: Arguments are invalid
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
 */
esp_err_t twai_get_status_info(twai_status_info_t *status_info);

/**
 * @brief   Clear the transmit queue
 *
 * This function will clear the transmit queue of all messages.
 *
 * @note    The transmit queue is automatically cleared when twai_stop() or
 *          twai_initiate_recovery() is called.
 *
 * @return
 *      - ESP_OK: Transmit queue cleared
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed or TX queue is disabled
 */
esp_err_t twai_clear_transmit_queue(void);

/**
 * @brief   Clear the receive queue
 *
 * This function will clear the receive queue of all messages.
 *
 * @note    The receive queue is automatically cleared when twai_start() is
 *          called.
 *
 * @return
 *      - ESP_OK: Transmit queue cleared
 *      - ESP_ERR_INVALID_STATE: TWAI driver is not installed
 */
esp_err_t twai_clear_receive_queue(void);

#ifdef __cplusplus
}
#endif

#endif //SOC_TWAI_SUPPORTED

pour gpio.h :
C:\Users\Utilisateur\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.5\tools\sdk\esp32s2\include\esp_rom\include\esp32s2\rom

// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef _ROM_GPIO_H_
#define _ROM_GPIO_H_

#include <stdint.h>
#include <stdbool.h>

#include "esp_attr.h"
#include "soc/gpio_reg.h"

#ifdef __cplusplus
extern "C" {
#endif

/** \defgroup gpio_apis, uart configuration and communication related apis
  * @brief gpio apis
  */

/** @addtogroup gpio_apis
  * @{
  */

#define GPIO_REG_READ(reg)              READ_PERI_REG(reg)
#define GPIO_REG_WRITE(reg, val)        WRITE_PERI_REG(reg, val)
#define GPIO_ID_PIN0                    0
#define GPIO_ID_PIN(n)                  (GPIO_ID_PIN0+(n))
#define GPIO_PIN_ADDR(i)                (GPIO_PIN0_REG + i*4)

#define GPIO_FUNC_IN_HIGH               0x38
#define GPIO_FUNC_IN_LOW                0x3C

#define GPIO_ID_IS_PIN_REGISTER(reg_id) \
    ((reg_id >= GPIO_ID_PIN0) && (reg_id <= GPIO_ID_PIN(GPIO_PIN_COUNT-1)))

#define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id) - GPIO_ID_PIN0)

typedef enum {
    GPIO_PIN_INTR_DISABLE = 0,
    GPIO_PIN_INTR_POSEDGE = 1,
    GPIO_PIN_INTR_NEGEDGE = 2,
    GPIO_PIN_INTR_ANYEDGE = 3,
    GPIO_PIN_INTR_LOLEVEL = 4,
    GPIO_PIN_INTR_HILEVEL = 5
} GPIO_INT_TYPE;

#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
        ((gpio_no < 32) ? gpio_output_set(bit_value<<gpio_no, (bit_value ? 0 : 1)<<gpio_no, 1<<gpio_no,0) : \
                         gpio_output_set_high(bit_value<<(gpio_no - 32), (bit_value ? 0 : 1)<<(gpio_no - 32), 1<<(gpio_no -32),0))
#define GPIO_DIS_OUTPUT(gpio_no)    ((gpio_no < 32) ? gpio_output_set(0,0,0, 1<<gpio_no) : gpio_output_set_high(0,0,0, 1<<(gpio_no - 32)))
#define GPIO_INPUT_GET(gpio_no)     ((gpio_no < 32) ? ((gpio_input_get()>>gpio_no)&BIT0) : ((gpio_input_get_high()>>(gpio_no - 32))&BIT0))

/* GPIO interrupt handler, registered through gpio_intr_handler_register */
typedef void (* gpio_intr_handler_fn_t)(uint32_t intr_mask, bool high, void *arg);

/**
  * @brief Initialize GPIO. This includes reading the GPIO Configuration DataSet
  *        to initialize "output enables" and pin configurations for each gpio pin.
  *        Please do not call this function in SDK.
  *
  * @param  None
  *
  * @return None
  */
void gpio_init(void);

/**
  * @brief Change GPIO(0-31) pin output by setting, clearing, or disabling pins, GPIO0<->BIT(0).
  *         There is no particular ordering guaranteed; so if the order of writes is significant,
  *         calling code should divide a single call into multiple calls.
  *
  * @param  uint32_t set_mask : the gpios that need high level.
  *
  * @param  uint32_t clear_mask : the gpios that need low level.
  *
  * @param  uint32_t enable_mask : the gpios that need be changed.
  *
  * @param  uint32_t disable_mask : the gpios that need diable output.
  *
  * @return None
  */
void gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask);

/**
  * @brief Change GPIO(32-39) pin output by setting, clearing, or disabling pins, GPIO32<->BIT(0).
  *         There is no particular ordering guaranteed; so if the order of writes is significant,
  *         calling code should divide a single call into multiple calls.
  *
  * @param  uint32_t set_mask : the gpios that need high level.
  *
  * @param  uint32_t clear_mask : the gpios that need low level.
  *
  * @param  uint32_t enable_mask : the gpios that need be changed.
  *
  * @param  uint32_t disable_mask : the gpios that need diable output.
  *
  * @return None
  */
void gpio_output_set_high(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask);

/**
  * @brief Sample the value of GPIO input pins(0-31) and returns a bitmask.
  *
  * @param None
  *
  * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO0.
  */
uint32_t gpio_input_get(void);

/**
  * @brief Sample the value of GPIO input pins(32-39) and returns a bitmask.
  *
  * @param None
  *
  * @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO32.
  */
uint32_t gpio_input_get_high(void);

/**
  * @brief Register an application-specific interrupt handler for GPIO pin interrupts.
  *        Once the interrupt handler is called, it will not be called again until after a call to gpio_intr_ack.
  *        Please do not call this function in SDK.
  *
  * @param gpio_intr_handler_fn_t fn : gpio application-specific interrupt handler
  *
  * @param void *arg : gpio application-specific interrupt handler argument.
  *
  * @return None
  */
void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg);

/**
  * @brief Get gpio interrupts which happens but not processed.
  *        Please do not call this function in SDK.
  *
  * @param None
  *
  * @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO0.
  */
uint32_t gpio_intr_pending(void);

/**
  * @brief Get gpio interrupts which happens but not processed.
  *        Please do not call this function in SDK.
  *
  * @param None
  *
  * @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO32.
  */
uint32_t gpio_intr_pending_high(void);

/**
  * @brief Ack gpio interrupts to process pending interrupts.
  *        Please do not call this function in SDK.
  *
  * @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO0.
  *
  * @return None
  */
void gpio_intr_ack(uint32_t ack_mask);

/**
  * @brief Ack gpio interrupts to process pending interrupts.
  *        Please do not call this function in SDK.
  *
  * @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO32.
  *
  * @return None
  */
void gpio_intr_ack_high(uint32_t ack_mask);

/**
  * @brief Set GPIO to wakeup the ESP32.
  *        Please do not call this function in SDK.
  *
  * @param uint32_t i: gpio number.
  *
  * @param GPIO_INT_TYPE intr_state : only GPIO_PIN_INTR_LOLEVEL\GPIO_PIN_INTR_HILEVEL can be used
  *
  * @return None
  */
void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state);

/**
  * @brief disable GPIOs to wakeup the ESP32.
  *        Please do not call this function in SDK.
  *
  * @param None
  *
  * @return None
  */
void gpio_pin_wakeup_disable(void);

/**
  * @brief set gpio input to a signal, one gpio can input to several signals.
  *
  * @param uint32_t gpio : gpio number, 0~0x2f
  *                        gpio == 0x3C, input 0 to signal
  *                        gpio == 0x3A, input nothing to signal
  *                        gpio == 0x38, input 1 to signal
  *
  * @param uint32_t signal_idx : signal index.
  *
  * @param bool inv : the signal is inv or not
  *
  * @return None
  */
void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv);

/**
  * @brief set signal output to gpio, one signal can output to several gpios.
  *
  * @param uint32_t gpio : gpio number, 0~0x2f
  *
  * @param uint32_t signal_idx : signal index.
  *                        signal_idx == 0x100, cancel output put to the gpio
  *
  * @param bool out_inv : the signal output is invert or not
  *
  * @param bool oen_inv : the signal output enable is invert or not
  *
  * @return None
  */
void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv);

/**
  * @brief Select pad as a gpio function from IOMUX.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_select_gpio(uint32_t gpio_num);

/**
  * @brief Set pad driver capability.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @param uint32_t drv : 0-3
  *
  * @return None
  */
void gpio_pad_set_drv(uint32_t gpio_num, uint32_t drv);

/**
  * @brief Pull up the pad from gpio number.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_pullup(uint32_t gpio_num);

/**
  * @brief Pull down the pad from gpio number.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_pulldown(uint32_t gpio_num);

/**
  * @brief Unhold the pad from gpio number.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_unhold(uint32_t gpio_num);

/**
  * @brief Hold the pad from gpio number.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_hold(uint32_t gpio_num);

/**
  * @brief enable gpio pad input.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_input_enable(uint32_t gpio_num);

/**
  * @brief disable gpio pad input.
  *
  * @param uint32_t gpio_num : gpio number, 0~0x2f
  *
  * @return None
  */
void gpio_pad_input_disable(uint32_t gpio_num);

/**
  * @}
  */

#ifdef __cplusplus
}
#endif

#endif /* _ROM_GPIO_H_ */

Je n'ai pas trop de temps pour y regarder car je pars pour une réunion de famille. J'y regarderai à mon retour.

Bon week-end.

Bonjour
Oui je suis bien sous Windows et j'ai regardé les fichiers que vous m'avez spécifiés mais j'ai rien trouvé de bien concluant.
Après je ne suis pas développeur et tout ceci est un peut compliqué à comprendre pour moi par moment.
J'ai donc testé une solution alternative en branchant un module MCP2515 sur l'ESP32-S2 à l'aide d'une interface SPI et ceci fonctionne correctement après de longue recherche pout trouver la bonne bibliothèque.
C'est tout de même dommage que je ne parvienne pas à faire fonctionner simplement une fonction qui est nativement implémentée dans la bibliothèque espressif (TWAI.h).

Bonsoir

Quel est le problême rencontré pour faire tourner l'exemple TWAIReceive.ini sur une carte Lolin S2 Mini ?

Il se compile sans problême , je ne peux aller plus loin faute de composants CAN

Si la proposition faite aux lignes 30 et 31 du code pour implanter les signaux RX et TX ne convient pas, que donne une autre implantation éfinie sur ces deux lignes ?

Les ESP32-S2 possèdent deux UARTS (pas 3 comme pour les ESP32 classiques) dont les RXn et Txn peuvent être positionnés presque sur n'importe quel GPIO , sauf cas particuliers.

Dans le fichier de configuration des S2 mini sous IDE Arduino Lolin à proposé par défaut, pour le premier UART les GPIO 37 et 39 pour une compatibilité matérielle avec diverses 'cartes filles' initialement proposées pour les cartes D1 mini à ESP8266
Cela peut être modifié.....le placement est libre
voir ici aux messages #20 et #21 :https://forum.arduino.cc/t/comment-utiliser-avec-esp32s2-laffichage-sur-port-serie/941511/21?page=2

Bonjour @al1fch

J'arrive à compiler l'exemple TWAIReceive. Là n'est pas le problème.

Le problème ait que je n'ai aucun retour sur la console série sauf les messages d'erreurs évoqués dans le fils du post.

Donc l'écriture dans la console est bonne puisque j'ai un retour avec les messages d'erreurs mais je n'arrive pas à avoir le retour de réception du can bus.

Comme évoqué avec les tests réalisés sous les conseils de @philippe86220 j'ai bien réussi à identifier les pins 37 et 39 pour le RX et le TX. J'ai aussi réalisé des tests sur les pins 1 et 2 et ça fonctionne aussi mais lorsque j'utilise l'exemple TWAIReceive ça ne fonctionne pas.

Comme je viens de le spécifier, j'arrive à avoir le signal canbus avec un module MCP2515.
Mais lorsque j'utilise le module SN65HVD230 ça ne fonctionne pas.

Aujourd'hui je suis sûre que ma compréhension du code est bonne puisque j'arrive à faire fonctionner les codes de can bus sur Arduino et ESP32 avec le module MCP2515.

Je suis aussi à peu près sûre que les pins RX=37 et TX=39 sont correct.

Donc il ne reste plus que 3 possibilités :

  • soit le TWAI ne fonctionne pas sous ESP32-S2
  • soit c'est le transceiver qui ne fonctionne pas. J'en ai 3 et j'ai testé les 3. Donc soit j'ai pas de chance soit c'est autre chose
  • autre possibilité, je n'arrive pas à configurer correctement les pins TX et RX pour la bibliothéque TWAI

Avec mes connaissances je ne vois que ça. Il y a peut être d'autres causes mais je ne vois pas.

Je referais des tests ce weekend ou dans la semaine mais jusque là je n'ai trouvé personne qui a réussi à faire du canbus sur ESP32-S2.

soit le TWAI ne fonctionne pas sous ESP32-S2

en lançant un moteur de recherche avec 'ESP32-S2 bug' on a plusieurs retours, rien ne dit que ce n'a pas té corrigé depuis

Je suis aussi à peu près sûre que les pins RX=37 et TX=39 sont correct.

oui, cest la localisation par défaut des entée/sortie du premier UART pour la LOLIN S2 MIni , ces 2 GPIO font l'affaire pour héberger RX et TX mais ne sont pas les seuls, RX et TX c'est 'où on veut, à condition de le demander'
Si 37 et 39 te conviennent , aucune raison de positioner ailleurs

Bonsoir
Bon je viens de refaire des tests qui ne fait que confirmer ce que j'ai écris précédemment :

  • l'ESP32-S2 fonctionne parfaitement avec un module MCP2515 et reçoit parfaitement le canbus de la voiture
  • l'ESP32-S2 ne fonctionne toujours pas avec le module SN65HVD230. J'ai testé 2 modules différents sans succès

Je suis vraiment à court d'idée

Bonjour ,
il faudrait admettre que tes 3 SN65HVD230 sont fake et envisager une autre source

Bonsoir @trimarco232

Je pense effectivement que je vais changer de module.

Je viens de commander 2 Adafruit CAN Pal - CAN Bus Transceiver - TJA1051T/3

Je les ai pris directement chez Adafruit donc en terme de qualité il ne devrez pas y avoir de soucis.

J'espère que ces modules répondront favorablement à ma problématique.

Suite des investigations dans quelques semaines le temps de recevoir les nouveaux modules.

tu peux aussi acquérir un esp32 "classique" , pour investiguer la problématique transceiver
(après tous tes efforts , t'es pas à 4€ près)
(le prix adafruit est des + corrects , quel est le coût après port et autres ? )