Skip to content

Commit 0226ef9

Browse files
authored
Add Esp32 send example (#38)
ESP32 example sending button state back to the EMUblack * Add ESP32 send example * add new example to CI test * Update README.md for CAN send examples
1 parent 4e0f8bd commit 0226ef9

File tree

4 files changed

+193
-0
lines changed

4 files changed

+193
-0
lines changed

.github/workflows/compile-examples.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ jobs:
4444
- source-path: ./
4545
sketch-paths: |
4646
- examples/EMUcan_ESP32/EMUcan_ESP32.ino
47+
- examples/EMUcan_ESP32_send/EMUcan_ESP32_send.ino
4748
4849
compile-sketch-teensy:
4950
runs-on: ubuntu-latest

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ This works with any CAN enabled device, MCP2515, Teensy, ESP32, STM32, Arduino U
2323
- [Status](#status)
2424
- [Reading the Values](#reading-the-values)
2525
- [Reading Flags](#reading-flags)
26+
- [Sending Data](#sending-data-to-emu-black-via-can-bus)
2627
- [Others](#others)
2728
- [Different Versions](#different-versions)
2829
- [Support](#support)
@@ -238,6 +239,18 @@ if (emucan.EMUcan_Status() == EMUcan_RECEIVED_WITHIN_LAST_SECOND) {
238239
}
239240
```
240241

242+
### Sending Data to EMU Black (via CAN Bus)
243+
244+
The following examples demonstrate how to format and send CAN bus messages compatible with the EMU Black ECU, using common hardware platforms. While these examples reside within the EMUcan project repository, they primarily illustrate the correct CAN message structure for sending data _to_ the EMU, which may not strictly require the `EMUcan` library itself for the transmission part.
245+
246+
- **Sending Analog Values (Example with MCP2515):**
247+
The [EMUcan_MCP2515_send](https://github.com/designer2k2/EMUcan/tree/main/examples/EMUcan_MCP2515_send) sketch shows how to send an analog value (e.g., a sensor reading) using an external MCP2515 CAN controller. It demonstrates the required CAN ID and data formatting.
248+
249+
- **Sending Digital Values (Example with ESP32):**
250+
The [EMUcan_ESP32_send](https://github.com/designer2k2/EMUcan/tree/main/examples/EMUcan_ESP32_send) sketch shows how to send a digital value (e.g., a switch state) using the ESP32's built-in CAN controller, again illustrating the necessary CAN message format.
251+
252+
These examples provide a practical guide for constructing and transmitting the CAN messages that the EMU Black expects to receive. You would typically use a standard CAN library appropriate for your hardware (like the ESP32 CAN (TWAI) driver or an MCP2515 library) to perform the actual transmission shown in these examples.
253+
241254
## Others
242255

243256
This Library is tested on Arduino Nano with a MCP2515 shield at 8Mhz.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<UserCANStream version="1.0">
3+
<tables>
4+
<symbol name="userCANStream" storage="ubyte" width="315" height="1" data="0 1 F7 0 0 0 0 0 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 11 1 32 0 0 7C 63 64 1 0 0 B4 66 64 35 11 1 2 0 0 23 71 1 1 10 0 22 71 1 23 71 1 1 10 0 22 71 1 1 11 0 0 0 0 97 70 1 1 10 0 98 70 1 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "/>
5+
</tables>
6+
</UserCANStream>
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// EMUCan Lib Test Example with sending to the EMU
2+
3+
// Example to be run on ESP32 with CAN Transceiver attached.
4+
// Configure the EMU Black to send the CAN Stream at 500KBPS
5+
6+
// Attach Switch or Button between SWITCH_1_PIN/SWITCH_2_PIN and ground.
7+
8+
// Configure custom CAN messages in the EMU Black:
9+
// Use this file: EMUBlackCANStreamExample.canstr
10+
// It will receive the values as CAN Switch #1 and #2
11+
12+
// https://www.designer2k2.at
13+
// Stephan Martin 02.04.2025
14+
15+
16+
#define SWITCH_1_PIN 32
17+
#define SWITCH_2_PIN 33
18+
19+
#include "EMUcan.h"
20+
// EMU initialized with base ID 600:
21+
EMUcan emucan(0x600);
22+
23+
// Needed for the CAN Interface on the ESP32 (called TWAI):
24+
#include "driver/twai.h"
25+
26+
// Pins used to connect to CAN bus transceiver:
27+
#define RX_PIN 21
28+
#define TX_PIN 22
29+
30+
#define PRINT_RATE_MS 500
31+
#define TRANSMIT_RATE_MS 1000
32+
unsigned long previousMillis = 0;
33+
unsigned long previousMillis_tx = 0;
34+
35+
void setup() {
36+
// put your setup code here, to run once:
37+
Serial.begin(115200);
38+
39+
Serial.print("EMUCAN_LIB_VERSION: ");
40+
Serial.println(EMUCAN_LIB_VERSION);
41+
42+
Serial.println("------- CAN Read ----------");
43+
44+
// Initialize configuration structures using macro initializers
45+
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TX_PIN, (gpio_num_t)RX_PIN, TWAI_MODE_NORMAL);
46+
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS(); //Look in the api-reference for other speed sets.
47+
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
48+
49+
// Install TWAI driver
50+
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
51+
Serial.println("Driver installed");
52+
} else {
53+
Serial.println("Failed to install driver");
54+
}
55+
56+
// Start TWAI driver
57+
if (twai_start() == ESP_OK) {
58+
Serial.println("Driver started");
59+
} else {
60+
Serial.println("Failed to start driver");
61+
}
62+
63+
// Reconfigure alerts to detect TX alerts and Bus-Off errors and RX queue full states
64+
uint32_t alerts_to_enable = TWAI_ALERT_RX_DATA | TWAI_ALERT_TX_IDLE | TWAI_ALERT_TX_SUCCESS | TWAI_ALERT_TX_FAILED | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR;
65+
if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) {
66+
Serial.println("CAN Alerts reconfigured");
67+
} else {
68+
Serial.println("Failed to reconfigure alerts");
69+
return;
70+
}
71+
72+
// Define Switch inputs with pullup:
73+
pinMode(SWITCH_1_PIN, INPUT_PULLUP);
74+
pinMode(SWITCH_1_PIN, INPUT_PULLUP);
75+
}
76+
77+
// CAN Bus send Switch States:
78+
void Send_CAN_Switch_States() {
79+
if (emucan.EMUcan_Status() == EMUcan_RECEIVED_WITHIN_LAST_SECOND) {
80+
byte CAN_Switch_State = 0;
81+
82+
bool CAN_Switch_1 = digitalRead(SWITCH_1_PIN);
83+
bool CAN_Switch_2 = digitalRead(SWITCH_1_PIN);
84+
85+
bitWrite(CAN_Switch_State, 0, CAN_Switch_1);
86+
bitWrite(CAN_Switch_State, 1, CAN_Switch_2);
87+
88+
Serial.print("Send Switch State over CAN: ");
89+
Serial.println(CAN_Switch_State, BIN);
90+
91+
// Configure message to transmit
92+
twai_message_t message;
93+
message.identifier = 0x0F7;
94+
message.data_length_code = 1;
95+
message.data[0] = CAN_Switch_State;
96+
//Sends the frame;
97+
// Queue message for transmission
98+
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
99+
Serial.println("Message queued for transmission");
100+
} else {
101+
Serial.println("Failed to queue message for transmission");
102+
}
103+
} else {
104+
Serial.println("Did not send Switch State over CAN due to no communication.");
105+
}
106+
}
107+
108+
void loop() {
109+
// put your main code here, to run repeatedly:
110+
111+
// Call the EMUcan lib with every received frame:
112+
uint32_t alerts_triggered;
113+
twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(1));
114+
twai_status_info_t twaistatus;
115+
twai_get_status_info(&twaistatus);
116+
if (alerts_triggered & TWAI_ALERT_RX_DATA) {
117+
// One or more messages received. Handle all.
118+
twai_message_t message;
119+
while (twai_receive(&message, 0) == ESP_OK) {
120+
emucan.checkEMUcan(message.identifier, message.data_length_code, message.data);
121+
}
122+
}
123+
124+
// Handle alerts
125+
if (alerts_triggered & TWAI_ALERT_ERR_PASS) {
126+
Serial.println("Alert: TWAI controller has become error passive.");
127+
}
128+
if (alerts_triggered & TWAI_ALERT_BUS_ERROR) {
129+
Serial.println("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.");
130+
Serial.printf("Bus error count: %lu\n", twaistatus.bus_error_count);
131+
}
132+
if (alerts_triggered & TWAI_ALERT_TX_FAILED) {
133+
Serial.println("Alert: The Transmission failed.");
134+
Serial.printf("TX buffered: %lu\t", twaistatus.msgs_to_tx);
135+
Serial.printf("TX error: %lu\t", twaistatus.tx_error_counter);
136+
Serial.printf("TX failed: %lu\n", twaistatus.tx_failed_count);
137+
}
138+
if (alerts_triggered & TWAI_ALERT_TX_SUCCESS) {
139+
Serial.println("Alert: The Transmission was successful.");
140+
Serial.printf("TX buffered: %lu\t", twaistatus.msgs_to_tx);
141+
}
142+
143+
// Send message every second:
144+
unsigned long currentMillis = millis();
145+
if (currentMillis - previousMillis_tx >= TRANSMIT_RATE_MS) {
146+
previousMillis_tx = currentMillis;
147+
Send_CAN_Switch_States();
148+
}
149+
150+
// Serial out Status every second:
151+
if (currentMillis - previousMillis >= PRINT_RATE_MS) {
152+
previousMillis = currentMillis;
153+
if (emucan.EMUcan_Status() == EMUcan_RECEIVED_WITHIN_LAST_SECOND) {
154+
Serial.print(emucan.emu_data.RPM);
155+
Serial.print(";");
156+
Serial.print(emucan.emu_data.TPS);
157+
Serial.print(";");
158+
Serial.print(emucan.emu_data.IAT);
159+
Serial.print(";");
160+
Serial.print(emucan.emu_data.MAP);
161+
Serial.print(";");
162+
Serial.println(emucan.emu_data.pulseWidth);
163+
} else {
164+
Serial.println("No communication from EMU");
165+
}
166+
if (emucan.emu_data.flags1 & emucan.F_IDLE) {
167+
Serial.println("Engine Idle active");
168+
}
169+
if (emucan.decodeCel()) {
170+
Serial.println("WARNING Engine CEL active");
171+
}
172+
}
173+
}

0 commit comments

Comments
 (0)