Reputation: 1598
I have created a simple circuit cor CANBUS (TWAI) communication between Arduino NANO and ESP32 Dev kit. At first I was using this library and my circuit works fine. this is te serial monitors:
But for ESP32 if I want to use TWAI library it is not responding and not working
this is TWAI codes:
#include <Arduino.h>
#include <driver/twai.h>
// Define the TWAI GPIO pins for ESP32 Dev Kit
const gpio_num_t RX_PIN = GPIO_NUM_4; // Change as needed
const gpio_num_t TX_PIN = GPIO_NUM_5; // Change as needed
// Define the TWAI configuration
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_PIN, RX_PIN, TWAI_MODE_NORMAL);
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
void setup() {
Serial.begin(115200);
while (!Serial); // Wait for the serial port to connect
delay(2000);
Serial.println("Initializing TWAI (CAN) Receiver...");
// Install TWAI driver
if (twai_driver_install(&g_config, &t_config, &f_config) != ESP_OK) {
Serial.println("Failed to install TWAI driver");
return;
}
// Start the TWAI driver
if (twai_start() != ESP_OK) {
Serial.println("Failed to start TWAI driver");
return;
}
Serial.println("TWAI (CAN) Receiver initialized");
}
void loop() {
twai_message_t message;
// Receive a TWAI message
if (twai_receive(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
Serial.print("Received a message with ID: 0x");
Serial.print(message.identifier, HEX);
if (message.rtr) {
Serial.println(" [Remote Request Frame]");
} else {
Serial.print(" Data Length: ");
Serial.println(message.data_length_code);
for (int i = 0; i < message.data_length_code; i++) {
Serial.print((char)message.data[i]);
}
Serial.println();
}
} else {
// No message received within 1 second
Serial.println("No message received");
}
}
also in Arduino ide examples > esp > twai > twaireceive code is not working CODE:
/* 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 4
#define TX_PIN 5
// Intervall:
#define POLLING_RATE_MS 1000
static bool driver_installed = false;
void setup() {
// Start Serial:
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_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");
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);
}
}
}
and RESULT:
12:21:11.915 -> Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.
12:21:11.915 -> Bus error count: 118
12:21:12.909 -> Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.
12:21:12.909 -> Bus error count: 119
12:21:12.909 -> Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.
12:21:12.909 -> Bus error count: 120
12:21:13.901 -> Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.
12:21:13.901 -> Bus error count: 121
I want to work with TWAI library. Because as a result I will use ESP32 s3 and this library can not support ESP32 S3.
Upvotes: 0
Views: 1284
Reputation: 1
I use this code to run a CAN-BUS between a ESP32-S3 and an ESP32 compiled with ESP32-core Version 2.0.17 (not core-Version 3.X !) ("classical") with CAN-BUS tranceivers TJA1051 which uses this library https://github.com/handmade0octopus/ESP32-TWAI-CAN/tree/master
// project remarks:
// On a ESP32-S3-board with DUAL-USB-C-connector the one that is shown as USB-enhanced SERIAL CH434
// is the one that used by Serial.
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
#define dbgi(myFixedText, variableName,timeInterval) \
{ \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
}
#define dbgc(myFixedText, variableName) \
{ \
static long lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
#define dbgcf(myFixedText, variableName) \
{ \
static float lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
/*
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
BlinkHeartBeatLED(OnBoard_LED,250);
static unsigned long MyTestTimer;
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
*/
#include <ESP32-TWAI-CAN.hpp>
// Showcasing simple use of ESP32-TWAI-CAN library driver.
// Default for ESP32
const byte CAN_TX = 5; // which means connect GPIO-Pin with this number with the Tx-output on the CAN-transeiver
const byte CAN_RX = 4; // which means connect GPIO-Pin with this number with the Rx-input on the CAN-transeiver
CanFrame rxFrame;
int myCounter;
unsigned long myLinksBlinkerTimer;
unsigned long myRechtsBlinkerTimer;
const byte linksBlinkerPin = 1;
const byte rechtsBlinkerPin = 2;
const byte fahrlichtPin = 42;
const byte linksBlinkerBitFilter = 0b00000001;
const byte rechtsBlinkerBitFilter = 0b00000010;
const byte FahrlichtBitFilter = 0b00000100;
const byte linksBlinkerBitClear = ~linksBlinkerBitFilter;
const byte rechtsBlinkerBitClear = ~rechtsBlinkerBitFilter;
const byte FahrlichtBitClear = ~FahrlichtBitFilter;
const byte onBoard_LED = 38;
void setup() {
digitalWrite(fahrlichtPin, LOW);
digitalWrite(linksBlinkerPin, LOW);
digitalWrite(rechtsBlinkerPin, LOW);
pinMode(linksBlinkerPin, OUTPUT);
pinMode(rechtsBlinkerPin, OUTPUT);
pinMode(fahrlichtPin, OUTPUT);
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
Serial.println();
Serial.print("linksBlinkerBitFilter binär:");
Serial.println(linksBlinkerBitFilter, BIN);
Serial.print("linksBlinkerBitClear binär:");
Serial.println(linksBlinkerBitClear, BIN);
// You can set custom size for the queues - those are default
byte QueueSize = 5;
ESP32Can.setRxQueueSize(QueueSize);
ESP32Can.setTxQueueSize(QueueSize);
Serial.print("ESP32Can.setRxQueueSize(");
Serial.print(QueueSize);
Serial.println(")");
Serial.print("ESP32Can.setTxQueueSize(");
Serial.print(QueueSize);
Serial.println(")");
int CAN_Speed = 500;
Serial.print("ESP32Can.begin(ESP32Can.convertSpeed(");
Serial.print(CAN_Speed);
Serial.print("), CAN_TX=");
Serial.print(CAN_TX);
Serial.print(", CAN_RX=");
Serial.print(CAN_RX);
Serial.print(", 10, 10) )");
Serial.println();
if (ESP32Can.begin(ESP32Can.convertSpeed(CAN_Speed), CAN_TX, CAN_RX, 10, 10) ) {
Serial.println("CAN bus started successfully!");
}
else {
Serial.println("starting CAN bus failed!");
}
}
void loop() {
BlinkHeartBeatLED(onBoard_LED, 250);
static byte links;
static byte rechts;
static unsigned long MyTestTimer;
/*
if ( TimePeriodIsOver(myLinksBlinkerTimer, 400) ) {
digitalWrite(linksBlinkerPin, !digitalRead(linksBlinkerPin) );
}
if ( TimePeriodIsOver(myRechtsBlinkerTimer, 250) ) {
digitalWrite(rechtsBlinkerPin, !digitalRead(rechtsBlinkerPin) );
}
*/
// You can set custom timeout, default is 1000 milliseconds
if (ESP32Can.readFrame(rxFrame, 100)) {
// Comment out if too many frames
Serial.printf("Received frame: %03X \r\n", rxFrame.identifier);
if (rxFrame.identifier == 0x7FF) { // Standard OBD2 frame responce ID
//dbgc("LR",rxFrame.data[7]);
// links = rxFrame.data[7] & 0b00000001; // xxy
links = rxFrame.data[7] & linksBlinkerBitFilter;
dbgc("L",links);
if ( links == 1) {
digitalWrite(linksBlinkerPin, HIGH);
//Serial.println("links HIGH");
}
else {
digitalWrite(linksBlinkerPin, LOW);;
//Serial.println("links LOW");
}
rechts = rxFrame.data[7] & 0b00000010;
dbgc("R",rechts);
if (rechts == 0b00000010) {
digitalWrite(rechtsBlinkerPin, HIGH);
//Serial.println("rechts HIGH");
}
else {
digitalWrite(rechtsBlinkerPin, LOW);;
//Serial.println("rechts LOW");
}
}
}
if ( TimePeriodIsOver(MyTestTimer, 1000) ) {
myCounter++;
if (myCounter > 999) {
myCounter = 0;
}
sendCanFrame('A', myCounter);
}
}
void sendCanFrame(uint8_t obdId, int Number) {
char myDigitBuffer[10] = " ";
itoa(Number, myDigitBuffer, 10); // itoa convert integer to ASCII-coded char-array
CanFrame myDataFrame = { 0 };
//obdFrame.identifier = 0x7DF; // Default OBD2 address;
myDataFrame.identifier = 0x7FF;
myDataFrame.extd = 0;
myDataFrame.data_length_code = 8;
myDataFrame.data[0] = myDigitBuffer[0];
myDataFrame.data[1] = myDigitBuffer[1];
myDataFrame.data[2] = myDigitBuffer[2];
myDataFrame.data[3] = 'H';
myDataFrame.data[4] = 'e';
myDataFrame.data[5] = 'l';
myDataFrame.data[6] = 'l';
myDataFrame.data[7] = 'o';
// Accepts both pointers and references
printCanFrame(myDataFrame);
ESP32Can.writeFrame(myDataFrame); // timeout defaults to 1 ms
}
void printCanFrame(CanFrame p_CAN_Frame) {
Serial.println("sending CAN-frame");
Serial.print("identifier=");
Serial.print(p_CAN_Frame.identifier, HEX);
Serial.print(" frame length=");
Serial.print(p_CAN_Frame.data_length_code);
Serial.print(" data as ASCII-Code#");
for (byte IdxNr = 0; IdxNr < 8; IdxNr++) {
Serial.print(char(p_CAN_Frame.data[IdxNr]) );
}
Serial.print("#");
Serial.println();
}
// helper-functions
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
ESP32-code
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
#define dbgi(myFixedText, variableName,timeInterval) \
{ \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
}
#define dbgc(myFixedText, variableName) \
{ \
static long lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
#define dbgcf(myFixedText, variableName) \
{ \
static float lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
/*
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
BlinkHeartBeatLED(OnBoard_LED,250);
static unsigned long MyTestTimer;
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
*/
#include <ESP32-TWAI-CAN.hpp>
#include <SafeString.h>
// Showcasing simple use of ESP32-TWAI-CAN library driver.
// Default for ESP32
const byte CAN_TX = 5; // which means connect GPIO-Pin with this number with the Tx-output on the CAN-transeiver
const byte CAN_RX = 4; // which means connect GPIO-Pin with this number with the Rx-input on the CAN-transeiver
CanFrame rxFrame;
int myCounter;
cSF(rxData_SS, 16);
unsigned long myLinksBlinkerTimer;
unsigned long myRechtsBlinkerTimer;
boolean linksBlinkerAn = false;
boolean rechtsBlinkerAn = false;
const byte linksBlinkerBitFilter = 0b00000001;
const byte rechtsBlinkerBitFilter = 0b00000010;
const byte FahrlichtBitFilter = 0b00000100;
const byte linksBlinkerBitClear = ~linksBlinkerBitFilter;
const byte rechtsBlinkerBitClear = ~rechtsBlinkerBitFilter;
const byte FahrlichtBitClear = ~FahrlichtBitFilter;
const byte linksBlinkerPin = 26;
const byte rechtssBlinkerPin = 27;
const byte switchedOn = LOW;
const byte switchedOff = HIGH;
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
Serial.println();
pinMode(linksBlinkerPin, INPUT_PULLUP);
pinMode(rechtssBlinkerPin, INPUT_PULLUP);
// You can set custom size for the queues - those are default
byte QueueSize = 5;
ESP32Can.setRxQueueSize(QueueSize);
ESP32Can.setTxQueueSize(QueueSize);
Serial.print("ESP32Can.setRxQueueSize(");
Serial.print(QueueSize);
Serial.println(")");
Serial.print("ESP32Can.setTxQueueSize(");
Serial.print(QueueSize);
Serial.println(")");
int CAN_Speed = 500;
Serial.print("ESP32Can.begin(ESP32Can.convertSpeed(");
Serial.print(CAN_Speed);
Serial.print("), CAN_TX=");
Serial.print(CAN_TX);
Serial.print(", CAN_RX=");
Serial.print(CAN_RX);
Serial.print(", 10, 10) )");
Serial.println();
if (ESP32Can.begin(ESP32Can.convertSpeed(CAN_Speed), CAN_TX, CAN_RX, 10, 10) ) {
Serial.println("CAN bus started successfully!");
}
else {
Serial.println("starting CAN bus failed!");
}
dbg("IO", digitalRead(linksBlinkerPin) );
dbg("IO", digitalRead(rechtssBlinkerPin) );
}
void loop() {
static unsigned long MyTestTimer;
dbgc("IO", digitalRead(linksBlinkerPin) );
dbgc("IO", digitalRead(rechtssBlinkerPin) );
if ( TimePeriodIsOver(myLinksBlinkerTimer, 1000) ) {
linksBlinkerAn = !linksBlinkerAn;
}
if ( TimePeriodIsOver(myRechtsBlinkerTimer, 250) ) {
//rechtsBlinkerAn = !rechtsBlinkerAn;
}
if ( TimePeriodIsOver(MyTestTimer, 50) ) {
//myCounter++;
if (myCounter > 999) {
myCounter = 0;
}
//sendCanFrame('A', myCounter);
}
// You can set custom timeout, default is 1000 milliseconds
if (ESP32Can.readFrame(rxFrame, 100)) {
// Comment out if too many frames
//Serial.printf("Received frame: %03X \r\n", rxFrame.identifier);
if (rxFrame.identifier == 0x7FF) { // Standard OBD2 frame responce ID
rxData_SS = "";
for (byte i = 0; i < 8; i++) {
rxData_SS += char( rxFrame.data[i] );
}
Serial.println(rxData_SS);
}
}
}
void sendCanFrame(uint8_t obdId, int Number) {
char myDigitBuffer[10] = " ";
itoa(Number, myDigitBuffer, 10); // itoa convert integer to ASCII-coded char-array
CanFrame myDataFrame = { 0 };
//obdFrame.identifier = 0x7DF; // Default OBD2 address;
myDataFrame.identifier = 0x7FF;
myDataFrame.extd = 0;
myDataFrame.data_length_code = 8;
myDataFrame.data[0] = myDigitBuffer[0];
myDataFrame.data[1] = myDigitBuffer[1];
myDataFrame.data[2] = myDigitBuffer[2];
myDataFrame.data[3] = 'H';
myDataFrame.data[4] = 'e';
myDataFrame.data[5] = 'l';
myDataFrame.data[6] = 'l';
if (linksBlinkerAn) {
//myDataFrame.data[7] = myDataFrame.data[7] | 0b00000001;
myDataFrame.data[7] = myDataFrame.data[7] | linksBlinkerBitFilter;
}
else {
myDataFrame.data[7] = myDataFrame.data[7] & linksBlinkerBitClear; // xxy
}
if (rechtsBlinkerAn) {
myDataFrame.data[7] = myDataFrame.data[7] | rechtsBlinkerBitFilter;
}
else {
myDataFrame.data[7] = myDataFrame.data[7] & rechtsBlinkerBitClear;
}
dbgc("LR", myDataFrame.data[7]);
//myDataFrame.data[7] = 'o';
// Accepts both pointers and references
printCanFrame(myDataFrame);
ESP32Can.writeFrame(myDataFrame); // timeout defaults to 1 ms
}
void printCanFrame(CanFrame p_CAN_Frame) {
Serial.println("sending CAN-frame");
Serial.print("identifier=");
Serial.print(p_CAN_Frame.identifier, HEX);
Serial.print(" frame length=");
Serial.print(p_CAN_Frame.data_length_code);
Serial.print(" data as ASCII-Code#");
for (byte IdxNr = 0; IdxNr < 8; IdxNr++) {
Serial.print(char(p_CAN_Frame.data[IdxNr]) );
}
Serial.print("#");
Serial.println();
}
// helper-functions
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
Upvotes: 0