CANBUS - FlexCANHi A very short intro at lecture room and then “Selfstudy/workshop”. You can call me by email. I will be available 15 min after intro lecture This page is organised as
Monday will be used for
NBNBNB: You can find many FlexCAN implementations out in “the cloud” The one above has been tested by Henrik and me and seems to work … Exercises for CANBUS partInspect code in
a) In the write call (starting from line 223) question; what is the difference in the outgoing part with timeout == 0 and timeout != 0 (and positive). b) in the read call (starting from line 170) question: how many rx buffers do we have ? c) write a test program for buffers you can run the code on one teensy if you connect skeleton
for (int i=0; i < 10; i++)
{
for (int a=0; a <=i; a++)
"write_a_canmsg - let databyte no 0 have values 0,1,2 acc to loop with "i"
read as many you can
}
What impact will it have to set timeout to 0 or 1 in the can pkg you use to receive data in when calling FlexCAN read (in line 170) some CANBUS stuffSee SELF STUDY PARTClocksTodays selfstudy is about clocks and ordering. Basic problem is ordering of events on different machines.
Today we can argue for that in many systems we can base and evaluate event ordering on time from satellites. In some cases this may not be possible. So … See a blog story which covers most of the stuff in a nice way. Primary Litterature
Exercises
Secondary litterature - is you have time
Some extra litteratureThis as just things I have found during the years. Dont read it for today m but might be nice to have :-) All litterature just above as a zip file CANBUS code for FlexCANCANbus Exercise
file canmastertime.ino
// --------------------------------------------------------------------
// DUAL Can program for teen sy 3.6CANtest for Teensy 3.6 dual CAN bus
// beerlicense Jens Dalsgaard Nielsen Oct 2017
// inspired by Pawelsky's dualcantest
//
// --------------------------------------------------------------------
#include <FlexCAN.h>
#ifndef __MK66FX1M0__
#error "Teensy 3.6 with dual CAN bus is required to run this example"
#endif
FlexCAN CANbus0(50000, 0, 1, 1); // 1 Mbit CAN0, 1,1 routes CAN0 to pins 29 & 30
FlexCAN CANbus1(50000, 1, 0, 0); // 1 Mbit CAN1 0,0 has no function - is always on pins 33 & 34
static CAN_message_t msgMasterBuf, msgSlaveBuf; // buffers for master and slave
//#define MASTER
// If MASTER is not defined (just above ) we define SLAVE
#ifndef MASTER
#define SLAVE
#endif
/*----------------------------------------------------------------
typedef struct CAN_message_t {
uint32_t id; // can identifier
uint8_t ext; // identifier is extended
uint8_t len; // length of data
uint16_t timeout; // milliseconds, zero will disable waiting
uint8_t buf[8];
} CAN_message_t;
----------------------------------------------------------------*/
void wrInt(uint8_t buf[], unsigned long i , int pos)
{
unsigned long ii;
ii = i;
memcpy(&buf[pos], &(ii), sizeof(unsigned long)); // copy int to array on position "pos"
}
unsigned long rdInt(uint8_t buf[], int pos)
{
unsigned long i;
memcpy(&i, &(buf[pos]), sizeof(unsigned long)); // copy int to array on position "pos"
return i;
}
void dataDump(uint8_t data[]) // just print 8 bytes data
{
int i;
Serial.print("CAN data: ");
for (i = 0; i < 8 ; i++) {
Serial.print(data[i]);
}
Serial.println("");
}
void CANPackageDump(CAN_message_t pk) // prints CAN package
{
// We just dump a CAN bus package on Serial
//
Serial.print("CAN package dump. objektID: ");
Serial.print(pk.id); // objektID in package
if (pk.ext == 1) {
Serial.print(" ext objektID (29 bit) ");
}
else {
Serial.print(" short objektID(11bit) ");
}
Serial.print(" ");
dataDump(pk.buf); // dump 8 byte data
}
void initMsg(CAN_message_t *pMessage, int objektID)
{
pMessage->id = objektID;
pMessage->ext = 0; // 11 bit objektID
pMessage->len = 8; // all 8 byte data shall be transmitted
for (int i = 0; i < 8; i++)
{
pMessage->buf[i] = i; // write 0,1,2,...,7 in 8 byte in buf
}
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------TRANSMIT AND RECEIVE FOR MASTER/SLAVE-----------
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// ------------USAGE OF the 8 byte data in buf -----------
// -------------------------------------------------------------
// -------------------------------------------------------------
/*
Layout and use of the 8 data bytes in the CAN bus packet
buf[0] : id of sender - legal interval 0-255
buf[1]: command (like 'R', 'W', 'C', 'T' etc
buf[2]: no of port for
buf[4]..buf[7]: 4 bytes used for transport of time (unsigned long)
R: read
W: write
C: config (port)
T: global time
*/
/*
master sends a time packet every 3 second
the time is pick up from millis plus an offset on 100.000.000
The offset is a dirty trick to be sure that two nodes can find each other
It only require they are powered up with a max time distance of 100.000.000 milliseconds
millis overflow at 2.000.000.000 So after 20 days the algoritms break as it is now
*/
const int masterID = 100;
const int slaveID = 101;
const int broadCastID = 50;
const int masterClockID = 05; // high pririty for clock use
const int timeBetweenTimePackets = 5000; // milli sec
int lastMasterTxTime = 0;
int masterTXCount = 0;
const unsigned long timeOff = 10000000;
unsigned long millisOffset = timeOff;
// our own millis timer syncronized function
unsigned long myMillis()
{
return millis() + millisOffset;
}
int noClockAdjustUp = 0, noClockAdjustDown = 0;
void setMyClock(unsigned long timeFromClockMaster)
{
unsigned long timeNow;
unsigned long adjustT;
timeNow = myMillis();
if ( timeNow < timeFromClockMaster) {
// locally we are behind masterclock
adjustT = (timeFromClockMaster - timeNow);
millisOffset += adjustT;
noClockAdjustUp++;
Serial.print(" offset(behind) adjust time no "); Serial.print(noClockAdjustUp);
Serial.print(" adj amount "); Serial.print(adjustT); Serial.print(" new offset "); Serial.println(millisOffset);
}
else if (timeFromClockMaster < timeNow ) {
// or we are ahead.
adjustT = (timeNow - timeFromClockMaster);
millisOffset -= adjustT;
Serial.print(" offset(ahead) adjust -time no "); Serial.print(noClockAdjustDown);
Serial.print(" adj amount "); Serial.print(adjustT); Serial.print(" new offset "); Serial.println(millisOffset);
noClockAdjustDown++;
// HMMMM what do you think about we can get same time again .. (back to the future syndrome)
}
else {
Serial.println(" no clock adjust");
}
}
void txMaster()
{
unsigned long test;
// if we are MASTER include the collowing code, othwerwises the txMAster function will just be empty
#ifdef MASTER
if ( timeBetweenTimePackets < (myMillis() - lastMasterTxTime ) ) { // has one second passed since last Tx ?
lastMasterTxTime = myMillis(); // for next second
// we add 1000000 bq we assume that from start there is less than 100000000 msec (100000 seconds) be startupTime of two nodes
wrInt(msgMasterBuf.buf, (lastMasterTxTime), 4); // copy lastMasterTxTime to can
//package buf array positions 4,5,6,7 (in the end)
test = rdInt(msgMasterBuf.buf, 4);
msgMasterBuf.id = masterClockID; // give it high prority (== low number)
msgMasterBuf.ext = 0;
msgMasterBuf.buf[0] = 'T'; // time package so everybody can recognize it
CANbus0.write(msgMasterBuf);
Serial.print("TX-MS int from master tx buf ");
Serial.print(test);
Serial.print(" org ");
Serial.println(lastMasterTxTime);
masterTXCount++; // now we have send one more
Serial.print("TX master clock: ");
Serial.println(myMillis());
}
#endif
}
// receive part for master
void rxMaster()
{
unsigned long timeFromClock;
if ( CANbus0.available() ) { // any messages arrived ?
Serial.println("RX-MS");
CANbus0.read(msgMasterBuf);
// is it for me ?
if (msgMasterBuf.id == masterID) {
Serial.println(" master received a for-me package");
switch (msgMasterBuf.buf[1]) {
case 'R':
break;
case 'W':
break;
case 'C':
break;
default :;
}
}
else if (msgMasterBuf.id == masterClockID) { // Is it a time sync package from clock master ?
// if we are not master we should be able to do clock stuff
// but for now we wil llet it be handled by the slave
// so time adjustment code is commented out here
#ifndef MASTER
// YES - double check it. There shall be a 'T' in buf[0];
if (msgMasterBuf.buf[0] == 'T') { // time sync package
timeFromClock = rdInt(msgMasterBuf.buf, 4); // lets get int which is in buf[4] .. buf[7] (int is size 4 bytes)
// no time adjustjment for now
// setMyClock(timeFromClock); // and set/test my local clock
Serial.print(" RX time pkg with time: ");
Serial.println(timeFromClock);
}
#endif
}
else {
Serial.print(" received a not-for-me packet with ID: ");
Serial.println(msgMasterBuf.id);
}
}
}
// receive and reply for slave
int slaveTXCount = 0;
void rxSlave()
{
unsigned long timeFromClock;==
if ( CANbus1.available() ) { // any messages arrived ?
CANbus1.read(msgSlaveBuf);
Serial.println("RX-SL");
// is it for us ?
if (msgSlaveBuf.id == slaveID) {
Serial.println("RX+ slave received a for-me package");
switch (msgSlaveBuf.buf[1]) {
case 'R':
msgSlaveBuf.id = masterID;
msgSlaveBuf.ext = 0; // 11 bit objektID
// here you can put info in package to master
CANbus1.write(msgSlaveBuf);
slaveTXCount++;
Serial.print(" TX slave: ");
Serial.println(slaveTXCount);
break;
case 'W':
break;
case 'C':
break;
default :;
}
}
// HERE WE DO CLOCK SYNC STUFF
else if (msgSlaveBuf.id == masterClockID) {
#ifndef MASTER
if (msgSlaveBuf.buf[0] == 'T') { // time sync package just an extra check
timeFromClock = rdInt(msgSlaveBuf.buf, 4); // lets get unsigned long (32 bit) which is in buf[4] .. buf[7]
Serial.print(" RX time pkg with time: ");
Serial.println(timeFromClock);
Serial.print(" local time is just now(ahead ?) ");
Serial.println( myMillis());
// I know it takes time to print - but it will make problem more visible - time
setMyClock(timeFromClock); // and set/test my local clock
// But this should be done with the slave on another node.
// we cant send time msg from myself to me.
// In this case transport delay will naturally every sync time give an adjustment
}
#endif
}
}
}
void initAndStartCan0AndCan1()
{
pinMode(28, OUTPUT); // add on driver board for CAN0 enable pin (active LOW)
pinMode(35, OUTPUT); // add on driver board for CAN1 enable pin (active LOW)
digitalWrite(28, LOW); // activate CAN bus transceiver/driver for can0
digitalWrite(35, LOW); // activate 230 canbus transceiver for can1
CANbus0.begin(); // intitalise and start CAN0 interface (to be used for master)
CANbus1.begin(); // ... - slave interface
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// ----------------------HERE WE START--------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
void setup(void)
{
pinMode(13, OUTPUT); // our famous LED on pin 13
Serial.begin(115200);
delay(1000); // let USb serial get time to be activated
Serial.println( sizeof(int));
Serial.print(" Ul "); Serial.println(sizeof(unsigned long));
Serial.println("Teensy 3.6 dual CAN bus timer test ");
initMsg(&msgMasterBuf, 100); // 100 is objektID which will be written in CAN package
initMsg(&msgSlaveBuf, 200); // 200 is ...
initAndStartCan0AndCan1();
Serial.println("gogo");
}
// -------------------------------------------------------------
void loop(void)
{
// service as fast as possible - so NO delay in the functions !!! please :-)
txMaster();
rxMaster();
rxSlave();
}
Another smart program
name of code dualclock01
// --------------------------------------------------------------------
// DUAL Can program for teen sy 3.6CANtest for Teensy 3.6 dual CAN bus
// beerlicense Jens Dalsgaard Nielsen Oct 2017
// inspired by Pawelsky's dualcantest
//
// --------------------------------------------------------------------
#include <FlexCAN.h>
#ifndef __MK66FX1M0__
#error "Teensy 3.6 with dual CAN bus is required to run this example"
#endif
/*----------------------------------------------------------------
BASIC struct to send and to receive CAN bus messages
typedef struct CAN_message_t {
uint32_t id; // can identifier
uint8_t ext; // identifier is extended
uint8_t len; // length of data
uint16_t timeout; // milliseconds, zero will disable waiting
uint8_t buf[8];
} CAN_message_t;
----------------------------------------------------------------*/
CAN_message_t msgMasterBuf, msgSlaveBuf; // buffers for master and slave
FlexCAN CANbus0(50000, 0, 1, 1); // 1 Mbit CAN0, 1,1 routes CAN0 to pins 29 & 30
FlexCAN CANbus1(50000, 1, 0, 0); // 1 Mbit CAN1 0,0 has no function - is always on pins 33 & 34
// --------- CONFIG PART -------------------
#define MASTERCLOCK
#define BUGPR(x) Serial.print(x)
// who is who and who am I ?
const int myMasterID = 100;
const int mySlaveID = 101;
const int broadCastID = 50;
const int masterClockID = 05; // high pririty for clock use
// -----------------oOo-----------------
void wrInt(uint8_t buf[], unsigned long i , int pos) // -- write int/long(32bit=4 byte) to an array
{
unsigned long ii;
ii = i;
memcpy(&buf[pos], &(ii), sizeof(unsigned long)); // copy int to array on position "pos"
}
unsigned long rdInt(uint8_t buf[], int pos) // -- read int/long(32bit=4 byte) to an array
{
unsigned long i;
memcpy(&i, &(buf[pos]), sizeof(unsigned long)); // copy int to array on position "pos"
return i;
}
void dataDump(CAN_message_t canPackage) // just print 8 bytes data (used for CANbus data buf
{
int i;
for (i = 0; i < 8 ; i++) {
BUGPR(canPackage.buf[i]);
BUGPR(" ");
}
}
void CANPackageDump(CAN_message_t pk) // prints CAN package
{
// We just dump a CAN bus package on Serial
//
if (pk.ext == 1) {
BUGPR(" (29 bit) ");
}
else {
BUGPR(" (11bit) ");
}
BUGPR("id length buf[8] ");
BUGPR(pk.id); // objektID in package
BUGPR(" ");
BUGPR(pk.len);
BUGPR(" : ");
dataDump(pk); // dump 8 byte data
BUGPR("\n");
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------TRANSMIT AND RECEIVE FOR MASTER/SLAVE-----------
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// ------------USAGE OF the 8 byte data in buf -----------
// -------------------------------------------------------------
// -------------------------------------------------------------
/*
Layout and use of the 8 data bytes in the CAN bus packet
buf[0] : id of sender - legal interval 0-255
buf[1]: command (like 'R', 'W', 'C', 'T' etc
buf[2]: no of port for
buf[4]..buf[7]: 4 bytes used for transport of time (unsigned long)
R: read
W: write
C: config (port)
T: global time
master sends a time packet every 3 second
the time is pick up from millis plus an offset on 100.000.000
The offset is a dirty trick to be sure that two nodes can find each other
It only require they are powered up with a max time distance of 100.000.000 milliseconds
millis overflow at 2.000.000.000 So after 20 days the algoritms break as it is now
*/
const int timeBetweenTimePackets = 5000; // milli sec
int lastMasterTxTime = 0; // time for last time sync/watch adjustement packet sedn from TxMasterr
int masterTXCount = 0; // and how many has been send
int noClockAdjustUp = 0, noClockAdjustDown = 0; // how many tiems has slave adjusted watch being behind or ahead
const unsigned long timeOff = 10000000; // Our startTime is 0 + ...
unsigned long millisOffset = 0; // time adjust part for slave
// our own millis timer syncronized function for everybody except TxMaster where it sneds tiem sync packages
//------------------------------------------------------oOo---------------------------------------
unsigned long myMillis()
{
return millis() + millisOffset; // millisOffset will change when watch is syncronized
}
//------------------------------------------------------oOo---------------------------------------
unsigned long masterClockMillis()
{
return millis() + timeOff; // timeOff is constant
}
//------------------------------------------------------oOo---------------------------------------
void setMyClock(unsigned long timeFromClockMaster)
{
unsigned long timeNow;
unsigned long adjustT;
timeNow = myMillis();
if ( timeNow < timeFromClockMaster) { // locally we are behind masterclock
adjustT = (timeFromClockMaster - timeNow);
millisOffset += adjustT;
noClockAdjustUp++;
BUGPR(" offset(behind) adjust time no "); BUGPR(noClockAdjustUp);
BUGPR(" adj amount "); BUGPR(adjustT); BUGPR(" new offset "); BUGPR(millisOffset);
BUGPR("\n");
}
else if (timeFromClockMaster < timeNow ) { // or we are ahead.
adjustT = (timeNow - timeFromClockMaster);
millisOffset -= adjustT;
noClockAdjustDown++;
BUGPR(" offset(ahead) adjust -time no "); BUGPR(noClockAdjustDown);
BUGPR(" adj amount "); BUGPR(adjustT); BUGPR(" new offset "); BUGPR(millisOffset);
BUGPR("\n");
// HMMMM what do you think about we can get same time again .. (back to the future syndrome)
}
else {
BUGPR(" no clock adjust this time\n");
}
}
//------------------------------------------------------oOo---------------------------------------
void tstAndSendTxClockSyncPackage()
{
#ifdef MASTERCLOCK
unsigned long timeNow;
timeNow = masterClockMillis();
if ( timeBetweenTimePackets < (timeNow - lastMasterTxTime ) ) { // has one second passed since last Tx ?
lastMasterTxTime = timeNow; // for next second
wrInt(msgMasterBuf.buf, timeNow, 4); // copy lastMasterTxTime to can
//package buf array positions 4,5,6,7 (in the end)
msgMasterBuf.id = masterClockID; // give it high prority (== low number)
msgMasterBuf.ext = 0; // 11 bit address
msgMasterBuf.buf[0] = 'T'; // time package so everybody can recognize it
msgMasterBuf.len = 8;
CANbus1.write(msgMasterBuf);
BUGPR("TX-MS int from master tx buf no");
BUGPR(masterTXCount);
BUGPR(" time now is: ");
BUGPR(timeNow);
BUGPR("\n");
masterTXCount++; // now we have send one more
}
#endif
}
//------------------------------------------------------oOo---------------------------------------
void txMaster()
{
// if we are MASTER include the collowing code, othwerwises the txMAster function will just be empty
#ifdef MASTERCLOCK
tstAndSendTxClockSyncPackage();
#endif
}
//------------------------------------------------------oOo---------------------------------------
void rxMasterPersonalPackage(CAN_message_t CANpk)
{
BUGPR(" master received a for-me package\n");
switch (CANpk.buf[1]) {
case 'R':
break;
case 'W':
break;
case 'C':
break;
// --------------------------------------------------------------------
// DUAL Can program for teen sy 3.6CANtest for Teensy 3.6 dual CAN bus
// beerlicense Jens Dalsgaard Nielsen Oct 2017
// inspired by Pawelsky's dualcantest
//
// --------------------------------------------------------------------
#include <FlexCAN.h>
#ifndef __MK66FX1M0__
#error "Teensy 3.6 with dual CAN bus is required to run this example"
#endif
/*----------------------------------------------------------------
BASIC struct to send and to receive CAN bus messages
typedef struct CAN_message_t {
uint32_t id; // can identifier
uint8_t ext; // identifier is extended
uint8_t len; // length of data
uint16_t timeout; // milliseconds, zero will disable waiting
uint8_t buf[8];
} CAN_message_t;
----------------------------------------------------------------*/
CAN_message_t msgMasterBuf, msgSlaveBuf; // buffers for master and slave
FlexCAN CANbus0(50000, 0, 1, 1); // 1 Mbit CAN0, 1,1 routes CAN0 to pins 29 & 30
FlexCAN CANbus1(50000, 1, 0, 0); // 1 Mbit CAN1 0,0 has no function - is always on pins 33 & 34
// --------- CONFIG PART -------------------
#define MASTERCLOCK
#define BUGPR(x) Serial.print(x)
// who is who and who am I ?
const int myMasterID = 100;
const int mySlaveID = 101;
const int broadCastID = 50;
const int masterClockID = 05; // high pririty for clock use
// -----------------oOo-----------------
void wrInt(uint8_t buf[], unsigned long i , int pos) // -- write int/long(32bit=4 byte) to an array
{
unsigned long ii;
ii = i;
memcpy(&buf[pos], &(ii), sizeof(unsigned long)); // copy int to array on position "pos"
}
unsigned long rdInt(uint8_t buf[], int pos) // -- read int/long(32bit=4 byte) to an array
{
unsigned long i;
memcpy(&i, &(buf[pos]), sizeof(unsigned long)); // copy int to array on position "pos"
return i;
}
void dataDump(CAN_message_t canPackage) // just print 8 bytes data (used for CANbus data buf
{
int i;
for (i = 0; i < 8 ; i++) {
BUGPR(canPackage.buf[i]);
BUGPR(" ");
}
}
void CANPackageDump(CAN_message_t pk) // prints CAN package
{
// We just dump a CAN bus package on Serial
//
if (pk.ext == 1) {
BUGPR(" (29 bit) ");
}
else {
BUGPR(" (11bit) ");
}
BUGPR("id length buf[8] ");
BUGPR(pk.id); // objektID in package
BUGPR(" ");
BUGPR(pk.len);
BUGPR(" : ");
dataDump(pk); // dump 8 byte data
BUGPR("\n");
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------TRANSMIT AND RECEIVE FOR MASTER/SLAVE-----------
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// ------------USAGE OF the 8 byte data in buf -----------
// -------------------------------------------------------------
// -------------------------------------------------------------
/*
Layout and use of the 8 data bytes in the CAN bus packet
buf[0] : id of sender - legal interval 0-255
buf[1]: command (like 'R', 'W', 'C', 'T' etc
buf[2]: no of port for
buf[4]..buf[7]: 4 bytes used for transport of time (unsigned long)
R: read
W: write
C: config (port)
T: global time
master sends a time packet every 3 second
the time is pick up from millis plus an offset on 100.000.000
The offset is a dirty trick to be sure that two nodes can find each other
It only require they are powered up with a max time distance of 100.000.000 milliseconds
millis overflow at 2.000.000.000 So after 20 days the algoritms break as it is now
*/
const int timeBetweenTimePackets = 5000; // milli sec
int lastMasterTxTime = 0; // time for last time sync/watch adjustement packet sedn from TxMasterr
int masterTXCount = 0; // and how many has been send
int noClockAdjustUp = 0, noClockAdjustDown = 0; // how many tiems has slave adjusted watch being behind or ahead
const unsigned long timeOff = 10000000; // Our startTime is 0 + ...
unsigned long millisOffset = 0; // time adjust part for slave
// our own millis timer syncronized function for everybody except TxMaster where it sneds tiem sync packages
//------------------------------------------------------oOo---------------------------------------
unsigned long myMillis()
{
return millis() + millisOffset; // millisOffset will change when watch is syncronized
}
//------------------------------------------------------oOo---------------------------------------
unsigned long masterClockMillis()
{
return millis() + timeOff; // timeOff is constant
}
//------------------------------------------------------oOo---------------------------------------
void setMyClock(unsigned long timeFromClockMaster)
{
unsigned long timeNow;
unsigned long adjustT;
timeNow = myMillis();
if ( timeNow < timeFromClockMaster) { // locally we are behind masterclock
adjustT = (timeFromClockMaster - timeNow);
millisOffset += adjustT;
noClockAdjustUp++;
BUGPR(" offset(behind) adjust time no "); BUGPR(noClockAdjustUp);
BUGPR(" adj amount "); BUGPR(adjustT); BUGPR(" new offset "); BUGPR(millisOffset);
BUGPR("\n");
}
else if (timeFromClockMaster < timeNow ) { // or we are ahead.
adjustT = (timeNow - timeFromClockMaster);
millisOffset -= adjustT;
noClockAdjustDown++;
BUGPR(" offset(ahead) adjust -time no "); BUGPR(noClockAdjustDown);
BUGPR(" adj amount "); BUGPR(adjustT); BUGPR(" new offset "); BUGPR(millisOffset);
BUGPR("\n");
// HMMMM what do you think about we can get same time again .. (back to the future syndrome)
}
else {
BUGPR(" no clock adjust this time\n");
}
}
//------------------------------------------------------oOo---------------------------------------
void tstAndSendTxClockSyncPackage()
{
#ifdef MASTERCLOCK
unsigned long timeNow;
timeNow = masterClockMillis();
if ( timeBetweenTimePackets < (timeNow - lastMasterTxTime ) ) { // has one second passed since last Tx ?
lastMasterTxTime = timeNow; // for next second
wrInt(msgMasterBuf.buf, timeNow, 4); // copy lastMasterTxTime to can
//package buf array positions 4,5,6,7 (in the end)
msgMasterBuf.id = masterClockID; // give it high prority (== low number)
msgMasterBuf.ext = 0; // 11 bit address
msgMasterBuf.buf[0] = 'T'; // time package so everybody can recognize it
msgMasterBuf.len = 8;
CANbus1.write(msgMasterBuf);
BUGPR("TX-MS int from master tx buf no");
BUGPR(masterTXCount);
BUGPR(" time now is: ");
BUGPR(timeNow);
BUGPR("\n");
masterTXCount++; // now we have send one more
}
#endif
}
//------------------------------------------------------oOo---------------------------------------
void txMaster()
{
// if we are MASTER include the collowing code, othwerwises the txMAster function will just be empty
#ifdef MASTERCLOCK
tstAndSendTxClockSyncPackage();
#endif
}
//------------------------------------------------------oOo---------------------------------------
void rxMasterPersonalPackage(CAN_message_t CANpk)
{
BUGPR(" master received a for-me package\n");
switch (CANpk.buf[1]) {
case 'R':
break;
case 'W':
break;
case 'C':
break;
default :;
}
}
//------------------------------------------------------oOo---------------------------------------
void doClockSync(CAN_message_t CANpk)
{
unsigned long timeFromClock;
timeFromClock = rdInt(CANpk.buf, 4); // lets get int which is in buf[4] .. buf[7] (int is size 4 bytes)
// no time adjustjment for now
setMyClock(timeFromClock); // and set/test my local clock
BUGPR(" RX time pkg with time: ");
BUGPR(timeFromClock);
BUGPR("\n");
}
// receive part for master
//------------------------------------------------------oOo---------------------------------------
void rxMaster()
{
unsigned long timeFromClock;
if ( CANbus1.available() ) { // any messages arrived ?
CANbus1.read(msgMasterBuf);
BUGPR("RX-MS\n");
if (msgMasterBuf.id == myMasterID) { // is it for me personally ?
rxMasterPersonalPackage(msgMasterBuf);
}
else if (msgMasterBuf.id == masterClockID) { // Is it a time sync package from clock master ?
// if we are not master we should be able to do clock stuff
// but for now we wil llet it be handled by the slave
// so time adjustment code is commented out here
// YES - double check it. There shall be a 'T' in buf[0];
if (msgMasterBuf.buf[0] == 'T') { // time sync package
doClockSync(msgMasterBuf);
}
}
else {
return;
BUGPR(" received a not-for-me packet with ID: ");
BUGPR(msgMasterBuf.id);
BUGPR("\n");
}
}
}
void rxSlavePersonalPackage(CAN_message_t CANpk)
{
BUGPR(" master received a for-me package");
switch (CANpk.buf[1]) {
case 'R':
CANpk.id = myMasterID;
CANpk.ext = 0; // 11 bit objektID
// here you can put info in package to master
CANbus1.write(CANpk);
BUGPR(" TX slave to ... ");
BUGPR(CANpk.id);
break;
case 'W':
break;
case 'C':
break;
default :;
}
BUGPR("\n");
}
// receive and reply for slave
//------------------------------------------------------oOo---------------------------------------
void rxSlave()
{
unsigned long timeFromClock;
if ( CANbus0.available() ) { // any messages arrived ?
CANbus0.read(msgSlaveBuf);
BUGPR("RX SL pak received ");
CANPackageDump(msgSlaveBuf);
if (msgSlaveBuf.id == mySlaveID) { // is it for us ?
BUGPR("RX+ slave received a for-me package\n");
rxSlavePersonalPackage(msgSlaveBuf);
}
// HERE WE DO CLOCK SYNC STUFF
else if (msgSlaveBuf.id == masterClockID) {
if (msgSlaveBuf.buf[0] == 'T') { // time sync package just an extra check
doClockSync(msgSlaveBuf);
}
}
}
}
//------------------------------------------------------oOo---------------------------------------
void initAndStartCan0AndCan1()
{
pinMode(28, OUTPUT); // add on driver board for CAN0 enable pin (active LOW)
pinMode(35, OUTPUT); // add on driver board for CAN1 enable pin (active LOW)
digitalWrite(28, LOW); // activate CAN bus transceiver/driver for can0
digitalWrite(35, LOW); // activate 230 canbus transceiver for can1
CANbus0.begin(); // intitalise and start CAN0 interface (to be used for master)
CANbus1.begin(); // ... - slave interface
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// ----------------------HERE WE START--------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
//------------------------------------------------------oOo---------------------------------------
void setup(void)
{
pinMode(13, OUTPUT); // our famous LED on pin 13
Serial.begin(115200);
delay(1000); // let USb serial get time to be activated
BUGPR("Teensy 3.6 dual CAN bus timer clock set test \n");
initAndStartCan0AndCan1();
BUGPR("gogo\n");
}
//------------------------------------------------------oOo---------------------------------------
void loop(void)
{
// service as fast as possible - so NO delay in the functions !!! please :-)
txMaster();
rxMaster();
rxSlave();
}
default :;
}
}
//------------------------------------------------------oOo---------------------------------------
void doClockSync(CAN_message_t CANpk)
{
unsigned long timeFromClock;
timeFromClock = rdInt(CANpk.buf, 4); // lets get int which is in buf[4] .. buf[7] (int is size 4 bytes)
// no time adjustjment for now
setMyClock(timeFromClock); // and set/test my local clock
BUGPR(" RX time pkg with time: ");
BUGPR(timeFromClock);
BUGPR("\n");
}
// receive part for master
//------------------------------------------------------oOo---------------------------------------
void rxMaster()
{
unsigned long timeFromClock;
if ( CANbus1.available() ) { // any messages arrived ?
CANbus1.read(msgMasterBuf);
BUGPR("RX-MS\n");
if (msgMasterBuf.id == myMasterID) { // is it for me personally ?
rxMasterPersonalPackage(msgMasterBuf);
}
else if (msgMasterBuf.id == masterClockID) { // Is it a time sync package from clock master ?
// if we are not master we should be able to do clock stuff
// but for now we wil llet it be handled by the slave
// so time adjustment code is commented out here
// YES - double check it. There shall be a 'T' in buf[0];
if (msgMasterBuf.buf[0] == 'T') { // time sync package
doClockSync(msgMasterBuf);
}
}
else {
return;
BUGPR(" received a not-for-me packet with ID: ");
BUGPR(msgMasterBuf.id);
BUGPR("\n");
}
}
}
void rxSlavePersonalPackage(CAN_message_t CANpk)
{
BUGPR(" master received a for-me package");
switch (CANpk.buf[1]) {
case 'R':
CANpk.id = myMasterID;
CANpk.ext = 0; // 11 bit objektID
// here you can put info in package to master
CANbus1.write(CANpk);
BUGPR(" TX slave to ... ");
BUGPR(CANpk.id);
break;
case 'W':
break;
case 'C':
break;
default :;
}
BUGPR("\n");
}
// receive and reply for slave
//------------------------------------------------------oOo---------------------------------------
void rxSlave()
{
unsigned long timeFromClock;
if ( CANbus0.available() ) { // any messages arrived ?
CANbus0.read(msgSlaveBuf);
BUGPR("RX SL pak received ");
CANPackageDump(msgSlaveBuf);
if (msgSlaveBuf.id == mySlaveID) { // is it for us ?
BUGPR("RX+ slave received a for-me package\n");
rxSlavePersonalPackage(msgSlaveBuf);
}
// HERE WE DO CLOCK SYNC STUFF
else if (msgSlaveBuf.id == masterClockID) {
if (msgSlaveBuf.buf[0] == 'T') { // time sync package just an extra check
doClockSync(msgSlaveBuf);
}
}
}
}
//------------------------------------------------------oOo---------------------------------------
void initAndStartCan0AndCan1()
{
pinMode(28, OUTPUT); // add on driver board for CAN0 enable pin (active LOW)
pinMode(35, OUTPUT); // add on driver board for CAN1 enable pin (active LOW)
digitalWrite(28, LOW); // activate CAN bus transceiver/driver for can0
digitalWrite(35, LOW); // activate 230 canbus transceiver for can1
CANbus0.begin(); // intitalise and start CAN0 interface (to be used for master)
CANbus1.begin(); // ... - slave interface
}
// -------------------------------------------------------------
// -------------------------------------------------------------
// ----------------------HERE WE START--------------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
//------------------------------------------------------oOo---------------------------------------
void setup(void)
{
pinMode(13, OUTPUT); // our famous LED on pin 13
Serial.begin(115200);
delay(1000); // let USb serial get time to be activated
BUGPR("Teensy 3.6 dual CAN bus timer clock set test \n");
initAndStartCan0AndCan1();
BUGPR("gogo\n");
}
//------------------------------------------------------oOo---------------------------------------
void loop(void)
{
// service as fast as possible - so NO delay in the functions !!! please :-)
txMaster();
rxMaster();
rxSlave();
}
Jens |