Bonjour, j'ai récemment acquis un arduino uno R4 wifi avec lequel je recois des messages CAN sous la forme : 10:11:52.433 -> [012CFE00] (8) : 00020000310206C0 . ces messages sont reçus via la bibliothèque Arduino_CAN.
Je suis bien content de recevoir ces messages mais je voudrai pouvoir en traiter les données. Je voudrai extraire l'identifiant CAN qui est une partie du début du message puis en fonction de cet id, lorsque les données m'intéressent traiter les données associées. donc aussi extraire les données qui sont la deuxième partie du message.
Le programme permettant d'avoir ces données est celui-ci:
void setup()
{
Serial.begin(115200);
while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_500k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
void loop()
{
if (CAN.available())
{
CanMsg const msg = CAN.read();
Serial.println(msg);//msg
}
}
waw! merci pour vos réponses si rapides!
Vous avez raison sur les bibliothèques utilisées, ce sont bien celles-ci.
Jai essayé d'extraire le message en String mais pas mal d'erreurs a la compilation (à suivre).
"msg" est peut être déjà au format string? je vais plancher sur le sujet et voir si j'arrive a extraire quelque chose...
message d'erreurs:
C:\Users\guesk\AppData\Local\Temp\.arduinoIDE-unsaved2024019-26668-1axcrve.5b8e\CANRead\CANRead.ino: In function 'void loop()':
C:\Users\guesk\AppData\Local\Temp\.arduinoIDE-unsaved2024019-26668-1axcrve.5b8e\CANRead\CANRead.ino:41:32: error: no matching function for call to 'arduino::String::String(const CanMsg&)'
String msgString = String(msg);
^
In file included from C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/IPAddress.h:24:0,
from C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/ArduinoAPI.h:30,
from C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/Arduino.h:4,
from C:\Users\guesk\AppData\Local\Temp\arduino\sketches\E4358362C443B977BB3557C15720809A\sketch\CANRead.ino.cpp:1:
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:83:11: note: candidate: arduino::String::String(double, unsigned char)
explicit String(double, unsigned char decimalPlaces=2);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:83:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'double'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:82:11: note: candidate: arduino::String::String(float, unsigned char)
explicit String(float, unsigned char decimalPlaces=2);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:82:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'float'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:81:11: note: candidate: arduino::String::String(long unsigned int, unsigned char)
explicit String(unsigned long, unsigned char base=10);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:81:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'long unsigned int'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:80:11: note: candidate: arduino::String::String(long int, unsigned char)
explicit String(long, unsigned char base=10);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:80:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'long int'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:79:11: note: candidate: arduino::String::String(unsigned int, unsigned char)
explicit String(unsigned int, unsigned char base=10);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:79:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'unsigned int'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:78:11: note: candidate: arduino::String::String(int, unsigned char)
explicit String(int, unsigned char base=10);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:78:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'int'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:77:11: note: candidate: arduino::String::String(unsigned char, unsigned char)
explicit String(unsigned char, unsigned char base=10);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:77:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'unsigned char'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:76:11: note: candidate: arduino::String::String(char)
explicit String(char c);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:76:11: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'char'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:75:2: note: candidate: arduino::String::String(arduino::String&&)
String(String &&rval);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:75:2: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'arduino::String&&'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:74:2: note: candidate: arduino::String::String(const arduino::__FlashStringHelper*)
String(const __FlashStringHelper *str);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:74:2: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'const arduino::__FlashStringHelper*'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:73:2: note: candidate: arduino::String::String(const arduino::String&)
String(const String &str);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:73:2: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'const arduino::String&'
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:72:2: note: candidate: arduino::String::String(const uint8_t*, unsigned int)
String(const uint8_t *cstr, unsigned int length) : String((const char*)cstr, length) {}
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:72:2: note: candidate expects 2 arguments, 1 provided
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:71:2: note: candidate: arduino::String::String(const char*, unsigned int)
String(const char *cstr, unsigned int length);
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:71:2: note: candidate expects 2 arguments, 1 provided
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:70:2: note: candidate: arduino::String::String(const char*)
String(const char *cstr = "");
^~~~~~
C:\Users\guesk\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.5\cores\arduino/api/String.h:70:2: note: no known conversion for argument 1 from 'const CanMsg {aka const arduino::CanMsg}' to 'const char*'
exit status 1
Compilation error: no matching function for call to 'arduino::String::String(const CanMsg&)'
idéalement il faudrait trouver le code de la classe CanMsg pour voir si on ne peut pas avoir simplement accès au éléments sous jacents qui doivent exister sans avoir à parser du texte.
Je n'ai pas cette carte et pas trop le temps de chercher mais j'avais une classe (PrintableString ) qui fonctionne avec Printable pour écrire dans une String
essayez avec ce code
class PrintableString : public Print {
public:
// Constructor for initializing with a C-style string
PrintableString(const char* str) : buffer(str) {}
virtual size_t write(uint8_t c) override {
buffer += (char)c;
return 1;
}
virtual size_t write(const uint8_t* buffer, size_t size) override {
size_t bytesWritten = 0;
while (size--) {
bytesWritten += write(*buffer++);
}
return bytesWritten;
}
size_t write(const char* str) {
return write(reinterpret_cast<const uint8_t*>(str), strlen(str));
}
size_t write(const String& str) {
return write(str.c_str(), str.length());
}
String getString() const {
return buffer;
}
PrintableString& operator=(const String& str) {
buffer = str;
return *this;
}
PrintableString& operator+=(const String& str) {
buffer += str;
return *this;
}
PrintableString& operator=(const char* str) {
buffer = str;
return *this;
}
PrintableString& operator+=(const char* str) {
buffer += str;
return *this;
}
private:
String buffer;
};
// ------------------
void setup()
{
Serial.begin(115200);
while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_500k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
void loop()
{
if (CAN.available())
{
CanMsg const msg = CAN.read();
PrintableString stringPrinter ="";
// on met le message dans un String (embarquée dans la classe PrintableString)
stringPrinter.print(msg);
Serial.println(stringPrinter.getString()); // maintenant on a la méthode getString() qui donne le texte
}
}
j'ai rajouté une petite classe écrite à la va vite qui sait récupérer le contenu d'une instance Printable dans une String. on pourra donc ensuite appeler getString() qui donnera le texte à analyser
merci de votre nouvelle réponse et du temps que vous me consacrez. Je n'arrive toujours pas a faire fonctionner le bout de programme que vous m'avez envoyé. j'ai des erreurs de compilation lié je pense aux dimensions des variables.
Aussi mon piètre niveau en c++ fait que je ne comprends pas "override" quand je le trouve dans CanMsg un peu partout. du coup et entre autre je n'arrive toujours pas a comprendre comment est créé msg. Je vais continuer encore les recherches de mon côté et tenter d'élever mes connaissances. je reviendrai vers vous plus tard et dans tous les cas jre mettrai ici la solution que je trouverai a mon problème.
Bonjour, j'ai réussi a bien avancer (suffisamment pour résoudre trois de mes gros problèmes).
Récupérer message CAN en HEXA avec bibliothèqe arduino_CAN.
Conversion Little indian en Big indian.
Conversion message virgule flottant au format hexa en float IEEE754.
Je viens d'essayer de placer quelques mots clés pouvant aider plusieurs d'entre nous.
J'ai trouvé une réponse qui m'a aidé dans un forum Arduino. un italien qui se plaignait de la bibliothèque ARDUINO_CAN qui n'est pas trop exploitable a partagé une solution exploitable.
/*
CANRead
Receive and read CAN Bus messages
See the full documentation here:
https://docs.arduino.cc/tutorials/uno-r4-wifi/can
https://www.arduino.cc/reference/fr/
*/
/**************************************************************************************
* INCLUDE
**************************************************************************************/
#include <Arduino_CAN.h>
/**************************************************************************************
* SETUP/LOOP
*************************************************************************************/
unsigned int idmessage=0;
void setup()
{
Serial.begin(115200);
while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_500k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
void loop()
{
if (CAN.available())
{
CanMsg const msg = CAN.read();//commande pour lire le message CAN
//cette partie sert a récupérer les octets en hexa du message CAN reçu (cest la réponse a ma demande dans le forum).
unsigned char buff[8] = {0,0,0,0,0,0,0,0};
idmessage=msg.getExtendedId() >>16 ; //Le décallage de 16 permettant de n'avoir que l'identifiant dont j'ai besoin en decimal.
unsigned int A=(msg.data[0]); //la commande pour récupérer les octets est celle ci (msg.data[numéro d'octet]).
unsigned int B=(msg.data[1]);
unsigned int C=(msg.data[2]);
unsigned int D=(msg.data[3]);
unsigned int E=(msg.data[4]);
unsigned int F=(msg.data[5]);
unsigned int G=(msg.data[6]);
unsigned int H=(msg.data[7]);
//dans la suite, mon msg CAN est en little indian (mots de poids fort a la fin du messgage) (voir divers sujets sur internet)
//et pour exploiter mes messages j'avais besoin de le passer en big indian (mot de poids fort en début de mesage).
//Du coup les quelques lignes suivantes inversent le message. (c'était aussi une de mes grosses galères)
unsigned int message=0; //mise a 0 de tous les octets de message
message=H<<24|G<<16|F<<8|E; //inversion du message (je le fait que pour E, F G H car mes messages sont doubles mais seule une partie sert).
/////////////////////////////////////////////////////////////////////////
// Il me paraîssait très compliqué de convertir ma valeur en Hexa en valeur flottante.
//c'était ma troisième grosse galère.en fait apprès de grosses rechercghes j'ai trouvé ceci:
//memcpy fait ça ntrès bien.(pas besoin de bibliothèque).
uint32_t binaryFloat32 =message;
float mcpyVal = 0;
memcpy (&mcpyVal,&binaryFloat32,sizeof (binaryFloat32));
Serial.print("valeur en float= ")
Serial.println(mcpyVal);
}
}
En tout cas merci pour votre aide bienveillante qui a pue m'aiguiller dans mes recherches.