Pier8283
Published © GPL3+

Wireless Dual CAN BUS Logger with PICO W

With Raspberry PICO W and a couple of CAN BUS interfaces it is possible to perform a simple wireless can bus logger

IntermediateWork in progress2 hours396
Wireless Dual CAN BUS Logger with PICO W

Things used in this project

Hardware components

Compute Module 4
Raspberry Pi Compute Module 4
×1
Raspberry Pi Compute Module 4 IO Board
×1
Raspberry Pi PICO W
×1
Dual Can PICO V1.0
×1
Dual CAN BUS Shield for Raspberry
×1

Software apps and online services

Raspbian
Raspberry Pi Raspbian
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)
Premium Female/Male Extension Jumper Wires, 40 x 6" (150mm)

Story

Read more

Schematics

SG Dual Can Bus setup

Code

PicoDualCan_V1.0_sniffer_wireless.ino

Arduino
//
//  SG Electronic Systems srls 
//  This Example is derived by
//  ACAN2515 Demo in loopback mode, for the Raspberry Pi Pico
//  Thanks to Duncan Greenwood for providing this sample sketch
//
// Pico Adapter Pinout
// SPI0_SCK         2     
// SPI0_MISO        0     
// SPI0_MOSI        3     
// SPI0_CS0         1     CAN0
// SPI0_CS1         9     CAN1      
// MCP2515_INT1     4     CAN0
// MCP2515_INT2     12    CAN1 
// SPI1_SCK         10    
// SPI1_MISO        8     
// SPI1_MOSI        11    
// SPI1_CS0         6     
// SPI1_CS1         13    
// I2C0_SDA         20    RTC
// I2C0_SCL         21    RTC
// I2C1_SDA         14    
// I2C1_SCL         15    
// LED1             18
// LED2             19
// UART0_RX         17
// UART0_TX         16

#if !( defined(ARDUINO_RASPBERRY_PI_PICO_W) )
	#error For RASPBERRY_PI_PICO_W only
#endif

#define _RP2040W_AWS_LOGLEVEL_     1
#define LED_OFF             LOW
#define LED_ON              HIGH

#define BUFFER_SIZE         4096 //2048
#define BUFFER_CAN          60
#define CAN_LOG             30 //10
char temp[BUFFER_SIZE];
#define LED1  18
#define LED2  19

#define LED
#define CAN0
#define CAN1
//#define RTC
//#define RTC_DS3231
//#define RTC_PCF85063
//
#include <Wire.h>
#ifdef RTC_DS3231
#include "DS3231.h"
#endif
#ifdef RTC_PCF85063
#include "PCF85063TP.h"
#endif
#include <ACAN2515.h>
#include <pico/cyw43_arch.h>
#include <AsyncWebServer_RP2040W.h>

char ssid[] = "your network SSID";        // your network SSID (name)
char pass[] = "your network password";         // your network password (use for WPA, or use as key for WEP), length must be 8+

int status = WL_IDLE_STATUS;

AsyncWebServer    server(80);

int reqCount = 0;                // number of requests received

//
// The Pico has two SPI peripherals, SPI and SPI1. Either (or both) can be used.
// The are no default pin assignments so they must be set explicitly.
// Testing was done with Earle Philhower's arduino-pico core:
// https://github.com/earlephilhower/arduino-pico
//

static const byte SPI0_SCK  = 2 ; // SCK input of MCP2515
static const byte SPI0_MOSI = 3 ; // SDI input of MCP2515
static const byte SPI0_MISO = 0 ; // SDO output of MCP2515
static const byte SPI0_CS0  = 1 ;  // CS input of MCP2515 1
static const byte SPI0_CS1  = 9 ;  // CS input of MCP2515 (2
static const byte I2C0_SDA  = 20 ; 
static const byte I2C0_SCL  = 21 ; 
#ifdef CAN0
static const byte MCP2515_INT0 = 4 ;  // INT output of MCP2515 (adapt to your design)
ACAN2515 can0 (SPI0_CS0, SPI, MCP2515_INT0) ;
#endif

#ifdef CAN1
static const byte MCP2515_INT1 = 12 ;  // INT output of MCP2515 (adapt to your design)
ACAN2515 can1 (SPI0_CS1, SPI, MCP2515_INT1) ;
#endif

#ifdef RTC_DS3231
#define DS3231_I2C_ADDRESS 0x68
#endif
#ifdef RTC_PCF85063
PCD85063TP clock;//define a object of PCD85063TP class
#endif

static const uint32_t QUARTZ_FREQUENCY = 16UL * 1000UL * 1000UL ; // 16 MHz
static uint32_t gBlinkLedDate0 = 0 ;
static uint32_t gReceivedFrameCount0 = 0 ;
static uint32_t gSentFrameCount0 = 0 ;
static uint32_t gBlinkLedDate1 = 0 ;
static uint32_t gReceivedFrameCount1 = 0 ;
static uint32_t gSentFrameCount1 = 0 ;

CANMessage frame0[CAN_LOG];
CANMessage frame1[CAN_LOG];
char can0_count = 0;
char can1_count = 0;
char can0_message_log[CAN_LOG][BUFFER_CAN];
char can1_message_log[CAN_LOG][BUFFER_CAN];


void handleRoot(AsyncWebServerRequest *request)
{
	static uint32_t pageCount   = 0;
	static uint32_t maxfreeHeap = 0;
	static uint32_t minFreeHeap = 0xFFFFFFFF;
	uint32_t curFreeHeap = rp2040.getFreeHeap();

	if (maxfreeHeap < curFreeHeap)
		maxfreeHeap = curFreeHeap;

	if (minFreeHeap > curFreeHeap)
		minFreeHeap = curFreeHeap;

	digitalWrite(LED_BUILTIN, LED_ON);

	int sec = millis() / 1000;
	int min = sec / 60;
	int hr = min / 60;
	int day = hr / 24;


	snprintf(temp, BUFFER_SIZE - 1,
"<html>\
<head>\
<meta http-equiv='refresh' content='5'/>\
<title>AsyncWebServer-%s</title>\
<style>\
body { background-color: #f1c40f; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\
</style>\
</head>\
<body>\
<h2>Dual CAN Bus wireless logger!</h2>\
<h3>SG Electronic Systems srls</h3>\
<h3>Running WiFi on %s</h3>\
<p>Uptime: %d d %02d:%02d:%02d, pageCount: %lu</p>\
<p>Heap Free: %lu, Max: %lu, Min: %lu</p>\
<h1>CAN0 and CAN1 message log</h1>\
<a href=\"can0log\"><button>CAN 0 LOG</button></a>&nbsp;\
<a href=\"can1log\"><button>CAN 1 LOG</button></a>\
<br>\
</body>\
</html>", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60, ++pageCount, curFreeHeap, maxfreeHeap, minFreeHeap );

	request->send(200, "text/html", temp);
 	digitalWrite(LED_BUILTIN, LED_OFF);
}

void  handleCan0(AsyncWebServerRequest *request)
{
	static uint32_t pageCount   = 0;
	static uint32_t maxfreeHeap = 0;
	static uint32_t minFreeHeap = 0xFFFFFFFF;
	uint32_t curFreeHeap = rp2040.getFreeHeap();

	if (maxfreeHeap < curFreeHeap)
		maxfreeHeap = curFreeHeap;

	if (minFreeHeap > curFreeHeap)
		minFreeHeap = curFreeHeap;

	digitalWrite(LED_BUILTIN, LED_ON);

	int sec = millis() / 1000;
	int min = sec / 60;
	int hr = min / 60;
	int day = hr / 24;
	snprintf(temp, BUFFER_SIZE - 1,
  "<html>\
  <head>\
  <meta http-equiv='refresh' content='5'/>\
  <title>AsyncWebServer-%s</title>\
  <style>\
  body { background-color: #f1c40f; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\
  </style>\
  </head>\
  <body>\
  <h2>Dual CAN Bus wireless logger!</h2>\
  <h3>SG Electronic Systems srls</h3>\
  <h3>Running WiFi on %s</h3>\
  <p>Uptime: %d d %02d:%02d:%02d, pageCount: %lu</p>\
  <p>Heap Free: %lu, Max: %lu, Min: %lu</p>\
  <h1>CAN0 message log</h1>\
  %s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>\
  %s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>\
  %s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>\
  <a href=\"home\"><button>BACK</button></a>&nbsp;\
  <a href=\"can1log\"><button>CAN 1 LOG</button></a>&nbsp;\
  <a href=\"can0logclear\"><button>CAN 0 RESET</button></a>\
  </body>\
  </html>", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60, ++pageCount, curFreeHeap, maxfreeHeap, minFreeHeap, 
  can0_message_log[0], can0_message_log[1], can0_message_log[2], can0_message_log[3], can0_message_log[4], 
  can0_message_log[5], can0_message_log[6], can0_message_log[7], can0_message_log[8], can0_message_log[9], 
  can0_message_log[10], can0_message_log[11], can0_message_log[12], can0_message_log[13], can0_message_log[14], 
  can0_message_log[15], can0_message_log[16], can0_message_log[17], can0_message_log[18], can0_message_log[19],
  can0_message_log[20], can0_message_log[21], can0_message_log[22], can0_message_log[23], can0_message_log[24], 
  can0_message_log[25], can0_message_log[26], can0_message_log[27], can0_message_log[28], can0_message_log[29]);

	request->send(200, "text/html", temp);
 	digitalWrite(LED_BUILTIN, LED_OFF);
}

void  handleCan1(AsyncWebServerRequest *request)
{
	static uint32_t pageCount   = 0;
	static uint32_t maxfreeHeap = 0;
	static uint32_t minFreeHeap = 0xFFFFFFFF;
	uint32_t curFreeHeap = rp2040.getFreeHeap();

	if (maxfreeHeap < curFreeHeap)
		maxfreeHeap = curFreeHeap;

	if (minFreeHeap > curFreeHeap)
		minFreeHeap = curFreeHeap;

	digitalWrite(LED_BUILTIN, LED_ON);

	int sec = millis() / 1000;
	int min = sec / 60;
	int hr = min / 60;
	int day = hr / 24;


	snprintf(temp, BUFFER_SIZE - 1,
  "<html>\
  <head>\
  <meta http-equiv='refresh' content='5'/>\
  <title>AsyncWebServer-%s</title>\
  <style>\
  body { background-color: #f1c40f; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\
  </style>\
  </head>\
  <body>\
  <h2>Dual CAN Bus wireless logger!</h2>\
  <h3>SG Electronic Systems srls</h3>\
  <h3>Running WiFi on %s</h3>\
  <p>Uptime: %d d %02d:%02d:%02d, pageCount: %lu</p>\
  <p>Heap Free: %lu, Max: %lu, Min: %lu</p>\
  <h1>CAN1 message log</h1>\
  %s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>\
  %s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>\
  %s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>%s<br>\
  <a href=\"home\"><button>BACK</button></a>&nbsp;\
  <a href=\"can0log\"><button>CAN 0 LOG</button></a>&nbsp;\
  <a href=\"can1logclear\"><button>CAN 1 RESET</button></a>\
  </body>\
  </html>", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60, ++pageCount, curFreeHeap, maxfreeHeap, minFreeHeap, 
  can1_message_log[0], can1_message_log[1], can1_message_log[2], can1_message_log[3], can1_message_log[4], 
  can1_message_log[5], can1_message_log[6], can1_message_log[7], can1_message_log[8], can1_message_log[9], 
  can1_message_log[10], can1_message_log[11], can1_message_log[12], can1_message_log[13], can1_message_log[14], 
  can1_message_log[15], can1_message_log[16], can1_message_log[17], can1_message_log[18], can1_message_log[19],
  can1_message_log[20], can1_message_log[21], can1_message_log[22], can1_message_log[23], can1_message_log[24], 
  can1_message_log[25], can1_message_log[26], can1_message_log[27], can1_message_log[28], can1_message_log[29] );

	request->send(200, "text/html", temp);
 	digitalWrite(LED_BUILTIN, LED_OFF);
}

void handleNotFound(AsyncWebServerRequest *request)
{
	digitalWrite(LED_BUILTIN, LED_ON);
	String message = "File Not Found\n\n";

	message += "URI: ";
	message += request->url();
	message += "\nMethod: ";
	message += (request->method() == HTTP_GET) ? "GET" : "POST";
	message += "\nArguments: ";
	message += request->args();
	message += "\n";

	for (uint8_t i = 0; i < request->args(); i++)
	{
		message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
	}

	request->send(404, "text/plain", message);
	digitalWrite(LED_BUILTIN, LED_OFF);
}

void printWifiStatus()
{
	// print the SSID of the network you're attached to:
	Serial.print("SSID: ");
	Serial.println(WiFi.SSID());

	// print your board's IP address:
	IPAddress ip = WiFi.localIP();
	Serial.print("Local IP Address: ");
	Serial.println(ip);

	// print your board's country code
	// #define CYW43_COUNTRY(A, B, REV) ((unsigned char)(A) | ((unsigned char)(B) << 8) | ((REV) << 16))
	uint32_t myCountryCode = cyw43_arch_get_country_code();
	char countryCode[3] = { 0, 0, 0 };

	countryCode[0] = myCountryCode & 0xFF;
	countryCode[1] = (myCountryCode >> 8) & 0xFF;

	Serial.print("Country code: ");
	Serial.println(countryCode);
}



void order_can0_message(void)
{
  int new_dx_can0 = can0_count;
  int count_total = gReceivedFrameCount0;
  for (int idx = 0; idx<CAN_LOG; idx++)
  {
    count_total = gReceivedFrameCount0 - CAN_LOG + idx ;
    if (count_total<0) count_total = 0;
    snprintf( can0_message_log[idx], BUFFER_CAN - 1, "N: %04d Id %03X Len: %d Msg: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X ", count_total, frame0[new_dx_can0].id, frame0[new_dx_can0].len,  
              frame0[new_dx_can0].data[0],  frame0[new_dx_can0].data[1],  frame0[new_dx_can0].data[2],  frame0[new_dx_can0].data[3],  
              frame0[new_dx_can0].data[4],  frame0[new_dx_can0].data[5],  frame0[new_dx_can0].data[6],  frame0[new_dx_can0].data[7]);    
    if (new_dx_can0<CAN_LOG)
    {
      new_dx_can0++;
    }
    else
    {
      new_dx_can0 = 0;
    }           
  }
}

void order_can1_message(void)
{
  int new_dx_can1 = can1_count;
  int count_total = gReceivedFrameCount1;
  for (int idx = 0; idx<CAN_LOG; idx++)
  {
    count_total = gReceivedFrameCount1 - CAN_LOG + idx ;
    if (count_total<0) count_total = 0;
    snprintf( can1_message_log[idx], BUFFER_CAN - 1, "N: %04d Id %03X Len: %d Msg: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X ", count_total, frame1[new_dx_can1].id, frame1[new_dx_can1].len,  
              frame1[new_dx_can1].data[0],  frame1[new_dx_can1].data[1],  frame1[new_dx_can1].data[2],  frame1[new_dx_can1].data[3],  
              frame1[new_dx_can1].data[4],  frame1[new_dx_can1].data[5],  frame1[new_dx_can1].data[6],  frame1[new_dx_can1].data[7]);    
    if (new_dx_can1<CAN_LOG)
    {
      new_dx_can1++;
    }
    else
    {
      new_dx_can1 = 0;
    }           
  }
}

//
//   SETUP
//

void setup () {

  #ifdef LED
  pinMode (LED1, OUTPUT) ;  // For CAN0
  digitalWrite (LED1, HIGH) ;
  pinMode (LED2, OUTPUT) ;  // For CAN1
  digitalWrite (LED2, HIGH) ;
  #else   //--- Switch on builtin led
  pinMode (LED_BUILTIN, OUTPUT) ;
  digitalWrite (LED_BUILTIN, HIGH) ;
  #endif
  //--- Start serial
  Serial.begin (115200) ;
  
  //--- Wait for serial (blink led at 10 Hz during waiting)
  while (!Serial&& millis() < 5000) {
    delay (50);
    #ifdef LED
    digitalWrite (LED1, !digitalRead (LED1)) ;
    delay (50);
    digitalWrite (LED2, !digitalRead (LED2)) ;
    #else
    digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
    #endif
  }


	Serial.print("\nStart Async_AdvancedWebServer on for Relay board ");
	Serial.print(BOARD_NAME);
	Serial.print(" with ");
	Serial.println(SHIELD_TYPE);
	Serial.println(ASYNCTCP_RP2040W_VERSION);
	Serial.println(ASYNC_WEBSERVER_RP2040W_VERSION);

	///////////////////////////////////

	// check for the WiFi module:
	if (WiFi.status() == WL_NO_MODULE)
	{
		Serial.println("Communication with WiFi module failed!");

		// don't continue
		while (true);
	}

	Serial.print(F("Connecting to SSID: "));
	Serial.println(ssid);

	status = WiFi.begin(ssid, pass);

	delay(1000);

	// attempt to connect to WiFi network
	while ( status != WL_CONNECTED)
	{
		delay(500);

		// Connect to WPA/WPA2 network
		status = WiFi.status();
	}

	printWifiStatus();

	///////////////////////////////////


	server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
	{
		handleRoot(request);
	});

  server.on("/home", HTTP_GET, [](AsyncWebServerRequest * request)
	{
		handleRoot(request);
	});

  server.on("/can0log", [](AsyncWebServerRequest * request)
	{
		order_can0_message();
    handleCan0(request);
	});

    server.on("/can1log", [](AsyncWebServerRequest * request)
	{
		order_can1_message();
    handleCan1(request);
	});

  server.on("/can0logclear", [](AsyncWebServerRequest * request)
	{
    memset(frame0, 0, sizeof(frame0));
    can0_count = 0;
    gReceivedFrameCount0 = 0;
		order_can0_message();
    handleCan0(request);
	});

  server.on("/can1logclear", [](AsyncWebServerRequest * request)
	{
    memset(frame1, 0, sizeof(frame1));
    can1_count = 0;
    gReceivedFrameCount1 = 0;
		order_can1_message();
    handleCan1(request);
	});


	server.onNotFound(handleNotFound);

	server.begin();

	Serial.print(F("AsyncWebServer is @ IP : "));
	Serial.println(WiFi.localIP());  
  //--- There are no default SPI pins so they must be explicitly assigned
  SPI.setSCK(SPI0_SCK);
  SPI.setTX(SPI0_MOSI);
  SPI.setRX(SPI0_MISO);
  //--- Begin SPI
  SPI.begin () ;
  #ifdef CAN0
  //--- Configure ACAN2515
  Serial.println ("Configure ACAN2515 CAN0") ;
  ACAN2515Settings settings0 (QUARTZ_FREQUENCY,  1000UL * 1000UL) ; // can1 bit rate 1000 kb/s
  settings0.mRequestedMode = ACAN2515Settings::NormalMode  ; // Select NormalMode  mode
  const uint16_t errorCode0 = can0.begin (settings0, [] { can0.isr () ; }) ;
  if (errorCode0 == 0) {
    Serial.print ("Bit Rate prescaler: ") ;
    Serial.println (settings0.mBitRatePrescaler) ;
    Serial.print ("Propagation Segment: ") ;
    Serial.println (settings0.mPropagationSegment) ;
    Serial.print ("Phase segment 1: ") ;
    Serial.println (settings0.mPhaseSegment1) ;
    Serial.print ("Phase segment 2: ") ;
    Serial.println (settings0.mPhaseSegment2) ;
    Serial.print ("SJW: ") ;
    Serial.println (settings0.mSJW) ;
    Serial.print ("Triple Sampling: ") ;
    Serial.println (settings0.mTripleSampling ? "yes" : "no") ;
    Serial.print ("Actual bit rate: ") ;
    Serial.print (settings0.actualBitRate ()) ;
    Serial.println (" bit/s") ;
    Serial.print ("Exact bit rate ? ") ;
    Serial.println (settings0.exactBitRate () ? "yes" : "no") ;
    Serial.print ("Sample point: ") ;
    Serial.print (settings0.samplePointFromBitStart ()) ;
    Serial.println ("%") ;
  } else {
    Serial.print ("Configuration 0 error 0x") ;
    Serial.println (errorCode0, HEX) ;
  }
  #endif
  delay (300);
  #ifdef CAN1
    //--- There are no default SPI pins so they must be explicitly assigned
  //--- Configure ACAN2515 CAN1
  Serial.println ("Configure ACAN2515 CAN1") ;
  ACAN2515Settings settings1 (QUARTZ_FREQUENCY, 1000UL * 1000UL) ; // can1 bit rate 1000 kb/s
  settings1.mRequestedMode = ACAN2515Settings::NormalMode  ; // Select NormalMode  mode
  const uint16_t errorCode1 = can1.begin (settings1, [] { can1.isr () ; }) ;
  if (errorCode1 == 0) {
    Serial.print ("Bit Rate prescaler: ") ;
    Serial.println (settings1.mBitRatePrescaler) ;
    Serial.print ("Propagation Segment: ") ;
    Serial.println (settings1.mPropagationSegment) ;
    Serial.print ("Phase segment 1: ") ;
    Serial.println (settings1.mPhaseSegment1) ;
    Serial.print ("Phase segment 2: ") ;
    Serial.println (settings1.mPhaseSegment2) ;
    Serial.print ("SJW: ") ;
    Serial.println (settings1.mSJW) ;
    Serial.print ("Triple Sampling: ") ;
    Serial.println (settings1.mTripleSampling ? "yes" : "no") ;
    Serial.print ("Actual bit rate: ") ;
    Serial.print (settings1.actualBitRate ()) ;
    Serial.println (" bit/s") ;
    Serial.print ("Exact bit rate ? ") ;
    Serial.println (settings1.exactBitRate () ? "yes" : "no") ;
    Serial.print ("Sample point: ") ;
    Serial.print (settings1.samplePointFromBitStart ()) ;
    Serial.println ("%") ;
  }else{
    Serial.print ("Configuration 1 error 0x") ;
    Serial.println (errorCode1, HEX) ;
  }  
  #endif

  #ifdef RTC
  Wire.setSDA(I2C0_SDA);
  Wire.setSCL(I2C0_SCL);
  Wire.begin();
  #endif
  #ifdef RTC_PCF85063 
  clock.begin();
  //clock.setcalibration(1, 32767.2);  // Setting offset by clock frequency
  uint8_t ret = clock.calibratBySeconds(0, -0.000041);
  Serial.print("offset value: ");
  Serial.print("0x");
  Serial.println(ret, HEX);
  #endif
}

#ifdef RTC_PCF85063 
void displayTime()
{
  char minute, hour, dayOfWeek, dayOfMonth, month, year, second;
  clock.getTime();
  second = clock.second;
  minute = clock.minute;
  hour = clock.hour;
  dayOfWeek = clock.dayOfWeek;
  dayOfMonth = clock.dayOfMonth;
  month = clock.month;
  year = clock.year+2000;
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:{
    Serial.println("Sunday");
    }
    break;
  case 2:{
    Serial.println("Monday");
  }
    break;
  case 3:{
    Serial.println("Tuesday");
  }
    break;
  case 4:{
    Serial.println("Wednesday");
  }
    break;
  case 5:{
    Serial.println("Thursday");
    }
    break;
  case 6:{
    Serial.println("Friday");
  }
    break;
  case 7:{
    Serial.println("Saturday");
  }
    break;
    default:
  Serial.println();
  break;
  } 
}
#endif

#ifdef RTC_DS3231
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte  minute, hour, dayOfWeek, dayOfMonth, month, year, second;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year); 
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:{
    Serial.println("Sunday");
    }
    break;
  case 2:{
    Serial.println("Monday");
  }
    break;
  case 3:{
    Serial.println("Tuesday");
  }
    break;
  case 4:{
    Serial.println("Wednesday");
  }
    break;
  case 5:{
    Serial.println("Thursday");
    }
    break;
  case 6:{
    Serial.println("Friday");
  }
    break;
  case 7:{
    Serial.println("Saturday");
  }
    break;
  }
  
}

#endif

void heartBeatPrint()
{
	static int num = 1;

	Serial.print(F("."));

	if (num == 80)
	{
		Serial.println();
		num = 1;
	}
	else if (num++ % 10 == 0)
	{
		Serial.print(F(" "));
	}
}

void check_status()
{
	static unsigned long checkstatus_timeout = 0;

#define STATUS_CHECK_INTERVAL     10000L

	// Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change.
	if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
	{
		heartBeatPrint();
		checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL;
	}
}

void loop () {

  CANMessage frame_read ;
  can0.poll () ;
  can1.poll () ;
  check_status();
  int len = 0;
  #ifdef CAN0
  if (can0.available ()) 
  {
      can0.receive (frame_read) ;
      gReceivedFrameCount0 ++ ;
      Serial.print ("CAN0 Received : ") ;
      Serial.print (gReceivedFrameCount0) ;
      Serial.print (" Id: ") ;
      len = frame_read.len;
      Serial.print (frame_read.id) ;
      Serial.print (" Len: ") ;
      Serial.print (len) ;
      Serial.print (" Data: ") ;
      for(int i = 0; i<len; i++)    // print the data
      {
        Serial.print(frame_read.data[i]);
        Serial.print(" ");
      }
      Serial.println();
      frame0[can0_count] = frame_read;
      if (can0_count<CAN_LOG)
      {
        can0_count++;
      }
      else
      {
        can0_count = 0;
      }
    
	#ifdef RTC
	displayTime();
	#endif
  }
  #endif
  #ifdef CAN1
  if (can1.available ()) 
  {
      can1.receive (frame_read) ;
      gReceivedFrameCount1 ++ ;
      Serial.print ("CAN 1 Received: ") ;
      Serial.print (gReceivedFrameCount1) ;
      Serial.print (" Id: ") ;
      len = frame_read.len;
      Serial.print (frame_read.id) ;
      Serial.print (" Len: ") ;
      Serial.print (len) ;
      Serial.print (" Data: ") ;
      for(int i = 0; i<len; i++)    // print the data
      {
        Serial.print(frame_read.data[i]);
        Serial.print(" ");
      }
      Serial.println();
      frame1[can1_count] = frame_read;
      if (can1_count<CAN_LOG)
      {
        can1_count++;
      }
      else
      {
        can1_count = 0;
      }
	#ifdef RTC
	displayTime();
	#endif
  }
  #endif
}

//

Credits

Pier8283

Pier8283

10 projects • 5 followers
Thanks to Duncan Greenwood and Majenko Technologies and Khoi Hoang.

Comments