Forum: Mikrocontroller und Digitale Elektronik LED über CAN-BUS schalten


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Ulrich W. (ruestmeister)


Lesenswert?

Hallo

Ich möchte gerne eine LED an einem ESP32 über eine Taste am anderen 
ESP32 und CAN-BUS schalten. Bin noch relativ neu beim ESP32 
programmieren und hänge jetzt ein bisschen. Die CAN Verbindung läuft 
schon. Auch kann ich schon die gesendeten Daten mit einem Tastendruck 
ändern. Aber beim Auslesen des Datenstrings und dem Schalten der LED 
habe ich noch Probleme da ich noch nicht ganz verstehe was da eigentlich 
wie gesendet wird. Auch die Suche im Internet hat mich noch nicht 
unbedingt schlauer gemacht. Habe folgenden Code. Das ist das Example von 
der Library "MCP_CAN" https://github.com/coryjfowler/MCP_CAN_lib
Habe nur beim Sender eine Variable "ggg" eingefügt die je nach 
Tastendruck entweder auf 0x00 oder 0x01 gesetzt wird. Eben dieses 0x00 
oder 0x01 würde ich gerne mit dem CAN-Receiver abfragen und die LED 
dementsprechend schalten.
Für Hilfe wie immer sehr dankbar.
Gruß Uli

CAN-Sender:
1
#include <Arduino.h>
2
3
// CAN Send Example
4
//
5
6
#include <mcp_can.h>
7
#include <SPI.h>
8
9
MCP_CAN CAN0(5);     // Set CS to pin 5
10
int ggg=0x00;
11
int inPin=2;
12
13
14
void setup()
15
{
16
  pinMode(inPin, INPUT_PULLUP);
17
  Serial.begin(115200);
18
19
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
20
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
21
  else Serial.println("Error Initializing MCP2515...");
22
23
  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted
24
}
25
26
27
28
void loop()
29
{
30
  
31
   if (digitalRead(inPin)==LOW){
32
    ggg = 0x01;
33
  } else {
34
    ggg = 0x00;
35
  }
36
  byte data[2] = {ggg, 0x01};
37
  // send data:  ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
38
  byte sndStat = CAN0.sendMsgBuf(0x100, 0, 2, data);
39
  if(sndStat == CAN_OK){
40
    Serial.println("Message Sent Successfully!");
41
  } else {
42
    Serial.println("Error Sending Message...");
43
  }
44
  delay(100);   // send data per 100ms
45
}
46
47
/*********************************************************************************************************
48
  END FILE
49
*********************************************************************************************************/
50
51
CAN-Receiver
52
53
#include <Arduino.h>
54
55
#include <mcp_can.h>
56
#include <SPI.h>
57
58
long unsigned int rxId;
59
unsigned char len = 0;
60
unsigned char rxBuf[8];
61
char msgString[128];                        // Array to store serial string
62
63
#define CAN0_INT 17                              // Set INT to pin 17
64
MCP_CAN CAN0(5);                               // Set CS to pin 5
65
int LED=2;
66
67
68
void setup()
69
{
70
  Serial.begin(115200);
71
  
72
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
73
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
74
    Serial.println("MCP2515 Initialized Successfully!");
75
  else
76
    Serial.println("Error Initializing MCP2515...");
77
  
78
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
79
80
  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
81
  
82
  Serial.println("MCP2515 Library Receive Example...");
83
  
84
}
85
86
87
88
void loop()
89
{
90
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
91
  {
92
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
93
    
94
    if((rxId & 0x80000000) == 0x80000000)     // Determine if ID is standard (11 bits) or extended (29 bits)
95
      sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len);
96
    else
97
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);
98
  
99
    Serial.print(msgString);
100
    if (rxId == 100){
101
      digitalWrite(LED, HIGH);
102
    } else{
103
      digitalWrite(LED, LOW);
104
    }
105
  
106
    if((rxId & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
107
      sprintf(msgString, " REMOTE REQUEST FRAME");
108
      Serial.print(msgString);
109
    } else {
110
      for(byte i = 0; i<len; i++){
111
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
112
        Serial.print(msgString);
113
      }
114
    }
115
        
116
    Serial.println();
117
  }
118
}
119
120
/*********************************************************************************************************
121
  END FILE
122
*********************************************************************************************************/

: Bearbeitet durch Moderator
von Harald A. (embedded)


Lesenswert?

An der Stelle, wo Du die ID auf 100 abfragst, musst Du die Daten in 
rxBuf prüfen, denn dort wird abgelegt, was Du gesendet hast. Dort wird 
also an den ersten beiden Bytes „ggg“ (rxBuf[0]) und 0x01 (rxBuf[1]) 
abgelegt.
Könnte übrigens sein, dass Du gleich angepflaumt wirst, weil Du den Code 
in den Text eingefügt hast - sei tapfer!

Übrigens (und dafür werde ich vlt. gleich angemacht werden): Lade mal 
genau die Programmschnipsel getrennt nacheinander bei ChatGPT hoch 
(einfach in den Chat Copy und Paste) und stelle deine spezifischen 
Fragen. Du wirst überrascht sein, was da geht und was Du lernen kannst.

Was ich Dir auch wärmstens empfehlen würde, wäre ein Logic Analyzer, 
einer für 10€ reicht. Damit kannst Du schön beobachten, was per SPI 
gesendet wird und was auf dem CAN los ist. Beim SPI kann man bei den 
langsamen LA zwar keine 10MBit machen, aber für den Anfang reichen ja 
auch mal 1MBit. Weiß nicht, was die Lib da voreinstellt.

Edit:
Habe es gerade mal in ChatGPT reingestellt, er schlägt folgenden Code 
vor:

void loop()
{
  if (!digitalRead(CAN0_INT)) // Wenn CAN0_INT-Pin niedrig ist, 
Nachricht empfangen
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf); // Nachricht lesen

    // Prüfen, ob die empfangene Nachricht die erwartete ID hat (hier 
0x100)
    if (rxId == 0x100)
    {
      // Extrahieren Sie den Wert von ggg aus den empfangenen Daten
      if (len >= 2) // Stellen Sie sicher, dass genug Daten empfangen 
wurden
      {
        ggg = rxBuf[0]; // Die erste Byte in rxBuf enthält ggg

        // Jetzt können Sie ggg verwenden, um die LED zu steuern
        if (ggg == 0x01)
        {
          digitalWrite(LED, HIGH); // LED einschalten
        }
        else
        {
          digitalWrite(LED, LOW); // LED ausschalten
        }
      }
      else
      {
        Serial.println("Nicht genug Daten empfangen.");
      }
    }
  }
}

: Bearbeitet durch User
von Ulrich W. (ruestmeister)


Lesenswert?

Wow! Ich habe ja schon davon gehört dass man chatGPT zum programmieren 
verwenden kann aber das plättet mich jetzt schon. Da werde ich mich wohl 
mal mit beschäftigen müssen. Vielen Dank für die schnelle und sehr 
hilfreiche Antwort. Und sorry dass ich den Code in den Text geschrieben 
habe.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.