Hi everyone,

I've been working on making a digital display for my megasquirt controlled Porsche 911, using the megasquirt's canbus broadcasting feature.

The basic setup is a teensy 3.2, a waveshare can converter, and a 2.4" Nextion "enhanced" touch display.

I'm essentially copying the work done by a user on here, I think he uses the name RaymondB. He gave the basic details here.

So, the project pretty much works at this point. I can get the teensy to read the canbus stream and send the data to the display.

There's a quick video of the display here.

So it works... but it's really buggy. Sometimes when it restarts no data will come through. Other times the data updates very, very slowly. It does the same thing whether I'm looking at the data on the display or in the serial monitor (I'm using Teensyduino).

I think the problems are related to FlexCAN. I'm currently using Teachop's library, as the Flexcan library that comes with Teensyduino won't work for me. Neither will any of the other libraries. I've read that the newer forks of Teachop's library don't work the same way but I can't really understand how any of the libraries work.

I'd like to get the display to show more data than it currently does (I have additional pages for data to be displayed) but if I do that, everything goes to hell. I also have some code written to change colors on the display, but things fall apart if I enable any of that as well.

I should also mention that I can make everything for the display work outside of the car (not using the canbus), so I don't think the issue is the nextion display. Also, as I mentioned before, I get the same stuttering and freezing in the serial monitor, even with the display disconnected.

I'd love to find a basic explanation of the various FlexCAN libraries, but there's very little out there on any of this. I think I've read through every thread on the forum and I gained a little bit of knowledge, but not enough to figure out where I'm going wrong.

I'm not sure how exactly to go about posting my sketch, so I'm just going to paste it in the message in case someone wants to take a look at it.



// Include FlexCAN library

#include <FlexCAN.h>

// Specify CAN baudrate (Currently 125k, 250k, 500k, 1M are supported in teensydrino 1.20)

int baud = 500000;

//int led = 13;
FlexCAN CANbus(baud);
static CAN_message_t rxmsg;

// Megasquirt data variables

byte indicator[7]; // where to store indicator data
float BATTV, IACstep, AFR, fuelCons, fuelFlow;
unsigned int MAP, spkAdv, RPM, TPS, MAT, CLT, syncCnt, VSS, gear, warmupCor, ecuTime;

int mapValueKpa;
float mapValuePSI;
int afrValue;

int mapGraphValue = 0; //value for the MAP progress bar
int afrGraphValue = 0; //value for the AFR progress bar
int rpmGraphValue = 0; //value for the RPM progress bar

int mapPic = 0; // value for switching MAP pic
int afrPic = 0; // value for AFR pic
int chtPic = 0; // value for CHT pic
int matPic = 0; // value for MAT display pic

int chtValue = 0;
int matValue = 0;

int mapThreshold = 8; // high/low threshold for MAP display
int afrLowThreshold = 11;
int afrHighThreshold = 16;
int chtThreshold = 225;
int matThreshold = 225;


void setup() {

// Serial1.begin(115200);
// Serial2.begin(115200); //the nextion file includes a provision to set the device baud at 115200, so we match that here

//delay(50);

Serial2.begin(9600);
Serial2.print("baud=115200");
Serial2.write(0xff); // We always have to send this three lines after each command sent to nextion.
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.end(); // End the serial comunication of baud=9600.

Serial2.begin(115200); // Start serial comunication at baud=115200.

CANbus.begin();

}

void loop() {

//Look for CAN broadcasts
if ( CANbus.read(rxmsg) ) {
switch (rxmsg.id) { // ID's 1520+ are Megasquirt CAN broadcast frames. Each frame represents a data group http://www.msextra.com/doc/pdf/Megas..._Broadcast.pdf
case 1512: // Group 0
MAP = (int)(word(rxmsg.buf[0], rxmsg.buf[1]));
RPM = (int)(word(rxmsg.buf[2], rxmsg.buf[3]));
CLT = (int)(word(rxmsg.buf[4], rxmsg.buf[5]));
TPS = (int)(word(rxmsg.buf[6], rxmsg.buf[7]));
break; }
}

if ( CANbus.read(rxmsg) ) {
switch (rxmsg.id) {
case 1513: // Group 1
MAT = (int)(word(rxmsg.buf[4], rxmsg.buf[5]));
spkAdv = (int)(word(rxmsg.buf[6], rxmsg.buf[7]));
break; }
}

if ( CANbus.read(rxmsg) ) {
switch (rxmsg.id) {
case 1514: // Group 2
AFR = rxmsg.buf[0];;
break; }
}

if ( CANbus.read(rxmsg) ) {
switch (rxmsg.id) {
case 1515: // Group 3
BATTV = (float)(word(rxmsg.buf[0], rxmsg.buf[1]));
break; }
}

if ( CANbus.read(rxmsg) ) {
switch (rxmsg.id) {
case 1562: // Group 42
VSS = (int)(word(rxmsg.buf[0], rxmsg.buf[1]));
break; }
}

//Data conversion and mapping

mapValueKpa = (MAP/10); // read the raw MAP value and convert it to kPa
mapValuePSI = (MAP*0.0145-14.7);
mapGraphValue = map(MAP, 0, 2000, 0, 100); // map it to graph range:

afrValue = (AFR/10);
afrGraphValue = map(afrValue, 0, 30, 0, 100);

// chtValue = (CLT/10);
// matValue = (MAT/10);

rpmGraphValue = map(RPM, 0, 8000, 0, 100);

//Display color changes


// if (mapValuePSI < mapThreshold && mapPic == 1) {
// Serial2.print("page0.mapPic.pic=");
// Serial2.print(0);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// mapPic = 0; //picValue variable is used so pic isn't continuously refreshed, instead only when it needs to change
// Serial2.print("page0.mapText.bco=");
// Serial2.print(0);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }
//
// if (mapValuePSI > mapThreshold && mapPic !=1) {
// Serial2.print("page0.mapPic.pic=");
// Serial2.print(1);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// mapPic = 1;
// Serial2.print("page0.mapText.bco=");
// Serial2.print(59652);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }

////AFR Display color changes

// if (afrValue > afrHighThreshold) {
// Serial2.print("page0.afrText.pco=");
// Serial2.print(59652);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }




// if (afrValue > afrLowThreshold && afrValue < afrHighThreshold && afrPic == 1) {
// Serial2.print("page0.afrPic.pic=");
// Serial2.print(2);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// afrPic = 0; //picValue variable is used so pic isn't continuously refreshed, instead only when it needs to change
// Serial2.print("page0.afrText.bco=");
// Serial2.print(0);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }
//
// if ((afrPic != 1) && (afrValue < afrLowThreshold || afrValue > afrHighThreshold)) {
// Serial2.print("page0.afrPic.pic=");
// Serial2.print(3);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// afrPic = 1;
// Serial2.print("page0.afrText.bco=");
// Serial2.print(59652);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }

//CHT Display color changes


// if (chtValue < chtThreshold && chtPic == 1) {
// Serial2.print("page0.chtPic.pic=");
// Serial2.print(4);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// chtPic = 0; //picValue variable is used so pic isn't continuously refreshed, instead only when it needs to change
// Serial2.print("page0.chtText.bco=");
// Serial2.print(0);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }
//
// if (chtValue > chtThreshold && chtPic !=1) {
// Serial2.print("page0.chtPic.pic=");
// Serial2.print(5);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// chtPic = 1;
// Serial2.print("page0.chtText.bco=");
// Serial2.print(59652);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }

//MAT Display color changes


// if (matValue < matThreshold && matPic == 1) {
// Serial2.print("page0.matPic.pic=");
// Serial2.print(6);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// matPic = 0; //picValue variable is used so pic isn't continuously refreshed, instead only when it needs to change
// Serial2.print("page0.matText.bco=");
// Serial2.print(0);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }
//
// if (matValue > matThreshold && matPic !=1) {
// Serial2.print("page0.matPic.pic=");
// Serial2.print(7);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// matPic = 1;
// Serial2.print("page0.matText.bco=");
// Serial2.print(59652);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
// }

//OUTPUT TO NEXTION
Serial2.print("page0.mapText.txt=");
Serial2.write(0x22);
Serial2.print(mapValuePSI, 1);
Serial2.write(0x22);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.print("page0.mapBar.val=");
Serial2.print(mapGraphValue);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.print("page0.afrText.txt=");
Serial2.write(0x22);
Serial2.print(AFR/10, 1);
Serial2.write(0x22);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.print("page0.afrBar.val=");
Serial2.print(afrGraphValue);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.print("page0.chtText.txt=");
Serial2.write(0x22);
Serial2.print(CLT/10);
Serial2.write(0x22);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.print("page0.matText.txt=");
Serial2.write(0x22);
Serial2.print(MAT/10);
Serial2.write(0x22);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

Serial2.print("page0.tpsBar.val=");
Serial2.print(TPS/10);
Serial2.write(0xff);
Serial2.write(0xff);
Serial2.write(0xff);

// Serial2.print("page1.rpmText.txt=");
// Serial2.write(0x22);
// Serial2.print(RPM);
// Serial2.write(0x22);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
//
// Serial2.print("page1.rpmBar.val=");
// Serial2.print(rpmGraphValue);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
//
// Serial2.print("page1.mphText.txt=");
// Serial2.write(0x22);
// Serial2.print(VSS/10);
// Serial2.write(0x22);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
//
// Serial2.print("page1.advText.txt=");
// Serial2.write(0x22);
// Serial2.print(spkAdv/10);
// Serial2.write(0x22);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);
//
// Serial2.print("page2.battText.txt=");
// Serial2.write(0x22);
// Serial2.print(BATTV/10);
// Serial2.write(0x22);
// Serial2.write(0xff);
// Serial2.write(0xff);
// Serial2.write(0xff);


//Serial.println(TPS/10);

//String text = "MAP:";
//text = String(text + String(MAP));
//text = String(text + " RPM: ");
//text = String(text + String(RPM));
//text = String(text + " TPS: ");
//text = String(text + String(TPS));
//text = String(text + " MAT: ");
//text = String(text + String(MAT));
//text = String(text + " CLT: ");
//text = String(text + String(CLT));
//text = String(text + " RPM: ");
//text = String(text + String(RPM));
//text = String(text + " AFR: ");
//text = String(text + String(AFR));
//text = String(text + " MPH: ");
//text = String(text + String(VSS));
//text = String(text + " BATT: ");
//text = String(text + String(BATTV));
//
//Serial.println(text);

}