No funciona CAN BUS en MEGA 2560

Hola

Tengo el siguiente codigo que me confirma el autor que funciona en Arduino Uno en can bus
yo lo he instalado en arduino mega 2560 conectando a los pins 50,51,52 y 53 y no me funciona.
he cambiado MCP_CAN CAN(10) por MCP_CAN CAN(53) pero sigue sin funcionar.
he visto en foros el mismo problema, pero no le he encontrado el motivo.

la placa can bus que tengo es la adjunta

cuando logre que lo detecte el software venus, (que según el creador funciona) tiene que leer los datos por el puerto serie para enviarlos por CAN. Pero primero que identifique el modulo

#include <mcp_can.h>
#include <SPI.h>

//variables for VE can
uint16_t chargevoltage = 49100; //max charge voltage in mv
uint16_t chargecurrent = 30000; //max charge current in ma
uint16_t disvoltage = 42000; // max discharge voltage in mv
uint16_t discurrent = 30000; // max discharge current in ma
uint16_t SOH = 100; // SOH place holder

unsigned char mes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char bmsname[8] = {'S', 'I', 'M', 'P', '-', 'B', 'M', 'S'};
unsigned char bmsmanu[8] = {'T', 'O', 'M', ' ', 'D', 'E', ' ', 'B'};

MCP_CAN CAN(53); //set CS pin for can controlelr

int SOC =80;

float PackVoltage = 46.7;
float AvgTemperature = 20.5;
uint16_t currentact = 0;

void setup() {

  Serial.begin(115200);
  
  // put your setup code here, to run once:
if(CAN.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
  else Serial.println("Error Initializing MCP2515...");

  CAN.setMode(MCP_NORMAL); 
}

void loop() {
  // put your main code here, to run repeatedly:
  VEcan();
  delay(200);
}


void VEcan() //communication with Victron system over CAN
{
  mes[0] = lowByte(chargevoltage / 100);
  mes[1] = highByte(chargevoltage / 100);
  mes[2] = lowByte(chargecurrent / 100);
  mes[3] = highByte(chargecurrent / 100);
  mes[4] = lowByte(discurrent / 100);
  mes[5] = highByte(discurrent / 100);
  mes[6] = lowByte(disvoltage / 100);
  mes[7] = highByte(disvoltage / 100);

  CAN.sendMsgBuf(0x351, 0, 8, mes);
Serial.println(" ");
for (int i = 0; i<8; i++)
{
  Serial.print(mes[i]);
  Serial.print(" , ");
}

  mes[0] = lowByte(SOC);
  mes[1] = highByte(SOC);
  mes[2] = lowByte(SOH);
  mes[3] = highByte(SOH);
  mes[4] = lowByte(SOC * 10);
  mes[5] = highByte(SOC * 10);
  mes[6] = 0;
  mes[7] = 0;

  CAN.sendMsgBuf(0x355, 0, 8, mes);
Serial.println(" ");
for (int i = 0; i<8; i++)
{
  Serial.print(mes[i]);
  Serial.print(" , ");
}

  mes[0] = lowByte(uint16_t(PackVoltage * 100));
  mes[1] = highByte(uint16_t(PackVoltage * 100));
  mes[2] = lowByte(uint16_t(currentact / 100));
  mes[3] = highByte(uint16_t(currentact / 100));
  mes[4] = lowByte(uint16_t(AvgTemperature * 10));
  mes[5] = highByte(uint16_t(AvgTemperature * 10));

  CAN.sendMsgBuf(0x356, 0, 8, mes);
Serial.println(" ");
for (int i = 0; i<8; i++)
{
  Serial.print(mes[i]);
  Serial.print(" , ");
}

  mes[0] = 0;
  mes[1] = 0;
  mes[2] = 0;
  mes[3] = 0;
  mes[4] = 0;
  mes[5] = 0;
  mes[6] = 0;
  mes[7] = 0;

  CAN.sendMsgBuf(0x35A, 0, 8, mes);

Serial.println(" ");
for (int i = 0; i<8; i++)
{
  Serial.print(mes[i]);
  Serial.print(" , ");
}

delay(5);
  CAN.sendMsgBuf(0x370, 0, 8, bmsname);

  Serial.println(" ");
for (int i = 0; i<8; i++)
{
  Serial.print(bmsname[i]);
  Serial.print(" , ");
}
delay(5);
  CAN.sendMsgBuf(0x35E, 0, 8, bmsmanu); 
Serial.println(" ");
for (int i = 0; i<8; i++)
{
  Serial.print(bmsmanu[i]);
  Serial.print(" , ");
}

}

Si el código te funciona en el UNO debería (ya se que no por ahora) funcionar en el MEGA.

MODELO  SS  MOSI  MISO  SCK
Mega    53  51    50    52

Aunque se que eso lo sabes no está de mas comenzar por lo básico.

Ahora que dice cuando se inicializa, da error?

  // put your setup code here, to run once:
if(CAN.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
  else Serial.println("Error Initializing MCP2515...");

no da ningun error
No tengo un arduino uno para probar, lo he probado directamente en el mega
me fio del autor

la otra parte que es un raspberry pi con el software VENUS para VICTRON funcionan perfectamente otros dispositios CAN BUS, conectados a la raspberry pi, o sea que tiene que detectar este.

Llevo poco tiempo con arduino asi, que puede haber cosas que se me escapen.

he descrifrado algunos datos:

235 , 1 , 44 , 1 , 44 , 1 , 164 , 1 ,
80 , 0 , 100 , 0 , 32 , 3 , 0 , 0 ,
62 , 18 , 0 , 0 , 205 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , // DEBE SER “MES”
83 , 73 , 77 , 80 , 45 , 66 , 77 , 83 , //ES EL BSMNAME SIMP-BMS
84 , 79 , 77 , 32 , 68 , 69 , 32 , 66 , //bsm FABRICANTE TOM DE B
235 , 1 , 44 , 1 , 44 , 1 , 164 , 1 ,
80 , 0 , 100 , 0 , 32 , 3 , 0 , 0 ,
62 , 18 , 0 , 0 , 205 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
83 , 73 , 77 , 80 , 45 , 66 , 77 , 83 ,
84 , 79 , 77 , 32 , 68 , 69 , 32 , 66 ,
235 , 1 , 44 , 1 , 44 , 1 , 164 , 1 ,

Deberia salir en este listado de equipos, si conecto en el can bus otro dispositivo si lo detecta

estos son los datos que en teoria envia por CANBUS, luego falta la parte que los lee desde el puerto serie que hay que implementar:

VEcan

Communicating with Victron energy products, also compatible with other inverters and solar equipement

Communication over canbus at 250kbps
Battery information for system to use;
-Battery Voltage
-Battery Current
-Battery Temperature
-Charge Voltage Limit
-Charge Current Limit
-Dischcarge Voltage Limit
-Discharge Current Limit
-SOH
-SOC

11-bit TX identifiers: 0x351, 0x355, 0x356, 0x35A, 0x35B, 0x35E, 0x35E, 0x370, 0x373, 0x374, 0x375, 0x376, 0x377,0x379 and 0x380.

11-bit RX heart-beat 0x305 message from CCGX is neglected.
CAN messages are sent every 200 ms.

lo curioso que en este otro post le ocurre lo mismo
https://forum.arduino.cc/?topic=588789#msg4008181

ya funciona con la siguiente modificacion:

Serial.begin(115200);         //puerto CAN BUS
  
 if(CAN.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK) Serial.print("El BUS CAN se ha iniciado correctamente!!\r\n");
  else Serial.print("Error en el inicio del BUS CAN!!\r\n");
  CAN.setMode(MCP_NORMAL); 
}

ahora tengo otro problema, como puedo añadir a void loop()

void loop()
{
  // put your main code here, to run repeatedly:
  VEcan();
  delay(200);
  
}

quiero añadir esta parte del programa, cuando lo adjunto deja de funcionar, estoy empezando , alguien me puede ayudar?

void loop()
{
  if (Serial1.available())
  {
    label = Serial1.readStringUntil('\t');                // lee los caracteres del buffer serie en una cadena. reads the label from the MPPT controller
    val = Serial1.readStringUntil('\r\r\n');              // lee los caracteres del buffer serie en una cadena.
    Serial.println (val);                              //lee y muestra los datos del puerto serie
    
     if (label == "V")                                    //(label) etiqueta voltaje bateria                  

    {
      val.toCharArray(buf, sizeof(buf));
      float valormedido = atof(buf);
      valormedido=valormedido/1000;
      dtostrf(valormedido, len, 2, BatteryA);
      BatteryA[len] = ' '; BatteryA[len + 1] = 0;
      tft.setTextColor(YELLOW, BLACK);
      tft.setCursor(130, 90);
      tft.print(BatteryA);
      
    }
    else if (label == "VPV")                               // (panel solar voltaje) label es la etiqueta y val es el valor de la etiqueta leida
    {
      val.toCharArray(buf, sizeof(buf));                    // By studying these small routines, you can modify to reading the parameters you want,
      float valormedido = atof(buf);
      valormedido=valormedido/1000;                       // calculating the correct value, see the Victron whitepaper for details. The value of label I is communicated in milli amps.
      dtostrf(valormedido, len, 2, panel);          
      panel[len] = ' '; panel[len + 1] = 0;
      tft.setTextColor(YELLOW, BLACK);
      tft.setCursor(130, 120);
      tft.print(panel);
    }
  }
}

Hola soy nuevo en Arduino, y me gustaria modificar este software para mi casa, ver el voltaje de la bateria en la pantalla venus

Como puedo hacer para mostrar la tension medida en el puerto serial1 “BatteryA” en el valor “PackVoltage” que ahora PackVoltage es fijo en 12.9. Quiero que muestre la tension medida en el puerto serie1

En la pantalla Display la puesta bien, pero no se como hacer para enviarlapor can bus y que se vea en la posicion PackVoltage.

#include <mcp_can.h>
#include <SPI.h>

#include <MCUFRIEND_kbv.h>
#include <Adafruit_GFX.h>    // Core graphics library

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
#define LCD_CS A3   // Chip Select goes to Analog 3
#define LCD_CD A2  // Command/Data goes to Analog 2
#define LCD_WR A1  // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

// Assign human-readable names to some common 16-bit color values:
#define BLACK           0x0000
#define RED             0xF800
#define GREEN           0x07E0
#define BLUE            0x102E
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define ORANGE          0xFD20
#define GREENYELLOW     0xAFE5
#define DARKGREEN       0x03E0
#define WHITE           0xFFFF
#define LIME            0x07E0

//lector serrial 1 ve direct
//byte len = 12;                   //variable len original de victron 
unsigned char len = 12;                              //Variable que indica la longitud de los datos
int intvalormedido;
String label, val;
String CS7 =  "";
float valormedido;
char buf[45];
char panel[6];
char BatteryA[6];
char voorloop[12];

//lector serial ve direct





MCUFRIEND_kbv tft;

//variables for VE can
uint16_t chargevoltage = 49100; //max charge voltage in mv
uint16_t chargecurrent = 30000; //max charge current in ma
uint16_t disvoltage = 42000; // max discharge voltage in mv
uint16_t discurrent = 30000; // max discharge current in ma
uint16_t SOH = 100; // SOH place holder


unsigned char alarm[4] = {0, 0, 0, 0};                          //Se crea un vector de caracteres de longitud 4
unsigned char mes[8] = {0, 0, 0, 0, 0, 0, 0, 0};                //Se crea un vector de caracteres de longitud 8
unsigned char bmsname[8] = {'D', 'I', 'Y', ' ', ' ',  'B', 'M', 'S'};
unsigned char bmsmanu[8] = {'T', 'O', 'M', ' ', 'D', 'E', ' ', 'B'};

MCP_CAN CAN(53); //set CS pin for can controlelr

//Variables for SOC calc
int SOC = 57; //State of Charge
//int SOCset = 0;
//uint16_t socvolt[4] = {3100, 10, 4100, 90};


float PackVoltage = 12.9;
float AvgTemperature = 23.5;
uint16_t currentact = 0;

//princiopio de display
unsigned long testText() {
  tft.fillScreen(BLACK);
  unsigned long start = micros();

  tft.setCursor(10, 0); //posicion del texto
  tft.setTextSize(3);
  tft.setTextColor(CYAN, BLACK);
  tft.println("   Test UART to CAN BUS");

  tft.setTextSize(3); //tamaño del texto
  tft.setTextColor(MAGENTA, BLACK);
  tft.setCursor(10, 40); //posicion del texto
  tft.println("      Probando......");

  tft.setCursor(10, 90); //posicion del texto
  tft.setTextSize(3);
  tft.setTextColor(YELLOW, BLACK);
  tft.println("Volt VE");
  tft.setCursor(400, 90); //posicion del texto
  tft.println("Volt");

  tft.setCursor(10, 120); //posicion del texto
  tft.setTextSize(3);
  tft.setTextColor(YELLOW, BLACK);
  tft.println("Panel");
  tft.setCursor(400, 120); //posicion del texto
  tft.println("Volt");

  return micros() - start;
}

///fin para display

void setup() {

  Serial1.begin(19200);          // Start communication with the MPPT controller, on the MEGA communication is through serial port 1
  CS7.toCharArray(voorloop, len);

  Serial.begin(115200);         //puerto CAN BUS

  if (CAN.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK) Serial.print("El BUS CAN se ha iniciado correctamente!!\r\n");
  else Serial.print("Error en el inicio del BUS CAN!!\r\n");
  CAN.setMode(MCP_NORMAL);


  // principio display no modificar

  uint16_t identifier = tft.readID();
  if (identifier == 0x9325) {

  }
  tft.begin(identifier);
  tft.setRotation(1);     // rotacion pantalla 0 vertical 1 horizontal

  Serial.print(F("Screen fill              "));
  Serial.println(testText());

}

void loop()   /// 
{
  if (Serial1.available())
  {
    label = Serial1.readStringUntil('\t');                // lee los caracteres del buffer serie en una cadena. reads the label from the MPPT controller
    val = Serial1.readStringUntil('\r\r\n');              // lee los caracteres del buffer serie en una cadena.
    Serial.println (val);                              //lee y muestra los datos del puerto serie

    if (label == "V")                                    //(label) etiqueta voltaje bateria

    {
      val.toCharArray(buf, sizeof(buf));
      float valormedido = atof(buf);
      valormedido = valormedido / 1000;
      dtostrf(valormedido, len, 2, BatteryA);
      BatteryA[len] = ' '; BatteryA[len + 1] = 0;
      tft.setTextColor(YELLOW, BLACK);
      tft.setCursor(130, 90);
      tft.print(BatteryA);
      
      //CAN.sendMsgBuf(0x351, 0, 8, BatteryA);        // prueba can jose envia can falta la direccion
    }
    else if (label == "VPV")                               // (panel solar voltaje) label es la etiqueta y val es el valor de la etiqueta leida
    {
      val.toCharArray(buf, sizeof(buf));                    // By studying these small routines, you can modify to reading the parameters you want,
      float valormedido = atof(buf);
      valormedido = valormedido / 1000;                   // calculating the correct value, see the Victron whitepaper for details. The value of label I is communicated in milli amps.
      dtostrf(valormedido, len, 2, panel);
      panel[len] = ' '; panel[len + 1] = 0;
      tft.setTextColor(YELLOW, BLACK);
      tft.setCursor(130, 120);
      tft.print(panel);

      
      //del puerto can bus
      VEcan();
      delay(200);


    }
  }
}

void VEcan() //communication with Victron system over CAN
{
  mes[0] = lowByte(chargevoltage / 100);
  mes[1] = highByte(chargevoltage / 100);
  mes[2] = lowByte(chargecurrent / 100);
  mes[3] = highByte(chargecurrent / 100);
  mes[4] = lowByte(discurrent / 100);
  mes[5] = highByte(discurrent / 100);
  mes[6] = lowByte(disvoltage / 100);
  mes[7] = highByte(disvoltage / 100);

  CAN.sendMsgBuf(0x351, 0, 8, mes);
  Serial.println(" ");
  for (int i = 0; i < 8; i++)
  {
    Serial.print(mes[i]);
    Serial.print(" , ");
  }

  mes[0] = lowByte(SOC);
  mes[1] = highByte(SOC);
  mes[2] = lowByte(SOH);
  mes[3] = highByte(SOH);
  mes[4] = lowByte(SOC * 10);
  mes[5] = highByte(SOC * 10);
  mes[6] = 0;
  mes[7] = 0;

  CAN.sendMsgBuf(0x355, 0, 8, mes);
  Serial.println(" ");
  for (int i = 0; i < 8; i++)
  {
    Serial.print(mes[i]);
    Serial.print(" , ");
  }

  mes[0] = lowByte(uint16_t(PackVoltage * 100));
  mes[1] = highByte(uint16_t(PackVoltage * 100));
  mes[2] = lowByte(uint16_t(currentact / 100));
  mes[3] = highByte(uint16_t(currentact / 100));
  mes[4] = lowByte(uint16_t(AvgTemperature * 10));
  mes[5] = highByte(uint16_t(AvgTemperature * 10));

  CAN.sendMsgBuf(0x356, 0, 8, mes);
  Serial.println(" ");
  for (int i = 0; i < 8; i++)
  {
    Serial.print(mes[i]);
    Serial.print(" , ");
  }

  mes[0] = 0;
  mes[1] = 0;
  mes[2] = 0;
  mes[3] = 0;
  mes[4] = 0;
  mes[5] = 0;
  mes[6] = 0;
  mes[7] = 0;

  CAN.sendMsgBuf(0x35A, 0, 8, mes);

  Serial.println(" ");
  for (int i = 0; i < 8; i++)
  {
    Serial.print(mes[i]);
    Serial.print(" , ");
  }

  delay(5);
  CAN.sendMsgBuf(0x370, 0, 8, bmsname);

  Serial.println(" ");
  for (int i = 0; i < 8; i++)
  {
    Serial.print(bmsname[i]);
    Serial.print(" , ");
  }
  delay(5);
  CAN.sendMsgBuf(0x35E, 0, 8, bmsmanu);
  Serial.println(" ");
  for (int i = 0; i < 8; i++)
  {
    Serial.print(bmsmanu[i]);
    Serial.print(" , ");
  }

}

El problema de esto

val = Serial1.readStringUntil('\r\n');

es que se queda esperando a que le des enter.
Porque dos \r?

Te lo dejé con uno o uncluso retira los \r y deja solo el \n

Prueba asi.

void loop() {
	// put your main code here, to run repeatedly:
	VEcan();

	if (Serial1.available())   {
		label = Serial1.readStringUntil('\t');              // lee los caracteres del buffer serie en una cadena. reads the label from the MPPT controller
		val = Serial1.readStringUntil('\r\r\n');            // lee los caracteres del buffer serie en una cadena.
		Serial.println (val);                              	// lee y muestra los datos del puerto serie

		if (label == "V") 	{ 								// (label) etiqueta voltaje bateria                 
			val.toCharArray(buf, sizeof(buf));
			float valormedido = atof(buf);
			valormedido = valormedido/1000;
			dtostrf(valormedido, len, 2, BatteryA);
			BatteryA[len] = ' '; BatteryA[len + 1] = 0;
			tft.setTextColor(YELLOW, BLACK);
			tft.setCursor(130, 90);
			tft.print(BatteryA);
		}
		if (label == "VPV")  {                            	// (panel solar voltaje) label es la etiqueta y val es el valor de la etiqueta leida
			val.toCharArray(buf, sizeof(buf));              // By studying these small routines, you can modify to reading the parameters you want,
			float valormedido = atof(buf);
			valormedido = valormedido/1000;                 // calculating the correct value, see the Victron whitepaper for details. The value of label I is communicated in milli amps.
			dtostrf(valormedido, len, 2, panel);         
			panel[len] = ' '; panel[len + 1] = 0;
			tft.setTextColor(YELLOW, BLACK);
			tft.setCursor(130, 120);
			tft.print(panel);
		}
	}
}

Y si no funciona, ajusta el setTimeout

Serial.setTimeout()
Description
Serial.setTimeout() sets the maximum milliseconds to wait for serial data. It defaults to 1000 milliseconds.

Serial.setTimeout() inherits from the Stream utility class.

Syntax
Serial.setTimeout(time)

en el setup() coloca algo como

Serial.setTimeout(200);

y lo haces coincidir con tu delay(200);

eso será lo que espere y debería devolverle el control al CANBUS.

Moderador:
Un doble posteo es una de las peores faltas en este foro.
La razón es que alguien que te responda en tu otro hilo se tomará el tiempo de darte una buena respuesta sin saber lo que se ha escrito en el otro sitio. Lo que consituye una perdida de tiempo para ambos foreros.
Por respeto a ellos es que te pido que no lo vuelvas a hacer y que leas las normas.

Normas del foro

Quizas me explique mal. Al principio no funcionaba en mega 2560 el codigo que estaba diseñado para arduino uno. Esto ya se soluciono y lo publique en un mensaje anterior.

Lo que preguntaba es como puedo enviar el dato leido por serial1
este dato u otro:

 if (label == "V")                                    //(label) etiqueta voltaje bateria

    {
      val.toCharArray(buf, sizeof(buf));
      float valormedido = atof(buf);
      valormedido = valormedido / 1000;
      dtostrf(valormedido, len, 2, BatteryA);
      BatteryA[len] = ' '; BatteryA[len + 1] = 0;
      tft.setTextColor(YELLOW, BLACK);
      tft.setCursor(130, 90);
      tft.print(BatteryA);
       //CAN.sendMsgBuf(0x351, 0, 8, BatteryA);        // prueba can jose envia can falta la direccion
    }

Enviarlo al can bus:

float PackVoltage = 12.9;

Al principio esta el codigo completo

El voltaje 12.9 se muestra a traves del can bus y quiero que el voltaje leido por serial1 con LABEL V se muestre en su lugar.

No se si me explico bien, a mi se me da mejor el hardware que el codigo.

Gracias