Auslesen CAN-BUS, RS-485 oder RS-232 (nur Auslesen)

22:04:48.088 -> Entering Configuration Mode Successful!
22:04:48.088 -> Setting Baudrate Successful!
22:04:48.088 -> MCP2515 Initialized Successfully!
22:04:48.088 -> MCP2515 Library Receive Example...
22:04:48.120 -> Standard ID: 0x001       DLC: 8  Data: 0x53 0x00 0x00 0x00 0x00 0x00 0x00 0x00
22:04:48.120 -> Standard ID: 0x002       DLC: 8  Data: 0x1A 0x00 0x18 0x00 0x00 0x00 0x00 0x00
22:04:48.120 -> Standard ID: 0x003       DLC: 4  Data: 0x00 0x00 0x00 0x00
22:04:48.155 -> Standard ID: 0x004       DLC: 8  Data: 0x00 0x00 0x20 0x00 0x00 0x00 0x00 0x00
22:04:48.155 -> Standard ID: 0x005       DLC: 8  Data: 0x00 0x00 0x00 0x20 0x00 0x00 0x90 0x01
22:04:48.155 -> Standard ID: 0x006       DLC: 8  Data: 0x54 0x00 0x91 0x00 0x00 0x00 0x00 0x00
22:04:48.194 -> Standard ID: 0x007       DLC: 8  Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x77 0x00
22:04:48.302 -> Standard ID: 0x001       DLC: 8  Data: 0x54 0x00 0x00 0x00 0x00 0x00 0x00 0x00
22:04:48.302 -> Standard ID: 0x002       DLC: 8  Data: 0x1A 0x00 0x18 0x00 0x00 0x00 0x00 0x00
22:04:48.302 -> Standard ID: 0x003       DLC: 4  Data: 0x00 0x00 0x00 0x00
22:04:48.338 -> Standard ID: 0x004       DLC: 8  Data: 0x00 0x00 0x20 0x00 0x00 0x00 0x00 0x00
22:04:48.338 -> Standard ID: 0x005       DLC: 8  Data: 0x00 0x00 0x00 0x20 0x00 0x00 0x90 0x01
22:04:48.372 -> Standard ID: 0x006       DLC: 8  Data: 0x54 0x00 0x91 0x00 0x00 0x00 0x00 0x00
22:04:48.372 -> Standard ID: 0x007       DLC: 8  Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x77 0x00

So kommt das raus, gerade nochmals angeschaut.
Standard Code aus der mcp_can Lib hierfür verwendet:

// CAN Receive Example
//

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

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];                        // Array to store serial string

#define CAN0_INT 2                              // Set INT to pin 2
// wenn von 2 auf andere Wert dann läuft der BUS
MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup()
{
  Serial.begin(57600);
  //Serial.begin(115200);
  //Serial.begin(9600);
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.

  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
    
    if((rxId & 0x80000000) == 0x80000000)     // Determine if ID is standard (11 bits) or extended (29 bits)
      sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len);
    else
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);
  
    Serial.print(msgString);
  
    if((rxId & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    } else {
      for(byte i = 0; i<len; i++){
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
        Serial.print(msgString);
      }
    }
        
    Serial.println();
  }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

#include <mcp_can.h>
#include <SPI.h>
#include <Streaming.h>     // https://github.com/janelia-arduino/Streaming

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];              // Array to store serial string

constexpr uint8_t CAN0_CS {10};   // Set CS to pin
MCP_CAN CAN0(CAN0_CS);

constexpr uint8_t CAN0_INT {2};   // Set INT to pin

struct CANDATA
{
  uint16_t batVoltage;
  uint16_t batCurrent;
  int32_t rpm;
  int16_t motoTemp;
  int16_t escTemp;
  int16_t externTemp;
  int16_t pwmOut;
  int16_t pwmIn;
  uint32_t error;
  uint32_t warning;
  uint32_t notice;
  uint16_t escInit;
  uint16_t bVoltage;
  uint16_t feedVoltage;
  uint16_t phaseCurrent;
  uint16_t avarangeCurrent;
  uint8_t busVoltage;
  uint8_t mosfetTemp;
};

CANDATA candata;
CANDATA olddata;

bool isNew;

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start...."));

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
  { Serial.println(F("MCP2515 Initialized Successfully!")); }
  else
  { Serial.println(F("Error Initializing MCP2515...")); }

  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
  pinMode(CAN0_INT, INPUT);                     // Configuring pin for /INT input
}

void loop()
{
  canRead();
  displayData();
}

void canRead()
{
  if (!digitalRead(CAN0_INT))                        // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)

    if ((rxId & 0x80000000) == 0x80000000)    // Determine if ID is standard (11 bits) or extended (29 bits)
    { sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len); }
    else
    { sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len); }

    Serial.print(msgString);

    if ((rxId & 0x40000000) == 0x40000000)    // Determine if message is a remote request frame.
    {
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    }
    else
    { splitCanMsg(); }

    Serial.println();
  }
}

void splitCanMsg()
{
  switch (rxId)
  {
    case 0x001:
      /*
        0x54 0x00           // [unsigned] Battery Voltage *0,1V    (8,4V)
        0x00 0x00           // [unsigned] Battery Current *0,1A
        0x00 0x00 0x00 0x00 // [signed] RPM
      */
      candata.batVoltage = rxBuf[0] | rxBuf[1];
      candata.batCurrent = rxBuf[2] | rxBuf[3];
      candata.rpm = rxBuf[4];
      candata.rpm += static_cast < uint32_t > (rxBuf[5]) << 8;
      candata.rpm += static_cast < uint32_t > (rxBuf[6]) << 16;
      candata.rpm += static_cast < uint32_t > (rxBuf[7]) << 24;
      break;

    case 0x002:
      /*
        0x00 0x00           // [signed] Motor Temp *1°C
        0x00 0x00           // [signed] ESC Temp *1°C
        0x00 0x00           // Reserved
        0x00 0x00           // [signed] Wenn ein externer Sensor verbaut ist *1°C
      */
      candata.motoTemp = rxBuf[0] | rxBuf[1];
      candata.escTemp = rxBuf[2] | rxBuf[3];
      candata.externTemp = rxBuf[6] | rxBuf[7];
      break;

    case 0x003:
      /*
        0x00 0x00           // [signed] Output PWM
        0x00 0x00           // [signed] Input PWM
      */
      candata.pwmOut = rxBuf[0] | rxBuf[1];
      candata.pwmIn = rxBuf[2] | rxBuf[3];
      break;

    case 0x004:
      /*
        0x00 0x00 0x20 0x00 // [unsigned] ERROR  (0000 0000 0000 0000 0010 0000 0000 0000)
        0x00 0x00 0x00 0x00 // [unsigned] WARNING
      */
      candata.error = rxBuf[0];
      candata.error += static_cast < uint32_t > (rxBuf[1]) << 8;
      candata.error += static_cast < uint32_t > (rxBuf[2]) << 16;
      candata.error += static_cast < uint32_t > (rxBuf[3]) << 24;
      candata.warning = rxBuf[4];
      candata.warning += static_cast < uint32_t > (rxBuf[5]) << 8;
      candata.warning += static_cast < uint32_t > (rxBuf[6]) << 16;
      candata.warning += static_cast < uint32_t > (rxBuf[7]) << 24;
      break;

    case 0x005:
      /*
        0x00 0x00 0x00 0x20 // [unsigned] Notice (0000 0000 0000 0000 0000 0000 0010 0000
        0x00 0x00           // Reserved
        0x90 0x01           // [unsigned] ESC INIT Status          (400)
      */
      candata.notice = rxBuf[0];
      candata.notice += static_cast < uint32_t > (rxBuf[1]) << 8;
      candata.notice += static_cast < uint32_t > (rxBuf[2]) << 16;
      candata.notice += static_cast < uint32_t > (rxBuf[3]) << 24;
      candata.escInit = rxBuf[6] | rxBuf[7];;
      break;

    case 0x006:
      /*
        0x54 0x00           // [unsigned] Battery Voltage *.1V     (8,4)
        0x94 0x00           // [unsigned] Feeding Voltage *.001V   (0,148)
        0x00 0x00           // [unsigned] Max Phase Current *1A
        0x00 0x00           // [unsigned] Average Phase Current *1A
      */
      candata.bVoltage = rxBuf[0] | rxBuf[1];
      candata.feedVoltage = rxBuf[2] | rxBuf[3];
      candata.phaseCurrent = rxBuf[4] | rxBuf[5];
      candata.avarangeCurrent = rxBuf[6] | rxBuf[7];
      break;

    case 0x007:
      /*
        0x00 0x00 0x00 0x00 0x00 0x00 // Reserved
        0x77                // [unsigned] Bus Voltage *0,1V        (11,9)
        0x00                // [unsigned] Mosfet Temperature *1°C
      */
      candata.busVoltage = rxBuf[4] | rxBuf[5];
      candata.mosfetTemp = rxBuf[6] | rxBuf[7];
      break;
  }
}

void displayData()
{
  static uint32_t lastmillis;

  if (millis() - lastmillis > 1000)
  {
    lastmillis = millis();
    isNew = true;
  }

  if (isNew)
  {
    Serial << F("Neuer Datensatz") << endl;
    Serial << F("Battery Voltage: ") << static_cast < float > (candata.batVoltage) * 0.1 << 'V' << endl;
    Serial << F("Battery Ampere: ") << static_cast < float > (candata.batCurrent) * 0.1 << 'A' << endl;
    Serial << F("RPM: ") << candata.rpm << "Umin" << endl;
    //candata.motoTemp;
    //candata.escTemp;
    //candata.externTemp;
    Serial << F("PWM Out: ") << static_cast < float > (candata.pwmOut) / 10.23 << '%' << endl;;
    //candata.pwmIn;
    Serial << F("EROORDATA: ") << _BIN(candata.error) << endl;
    Serial << F("Warnings: ") << _BIN(candata.warning) << endl;
    //candata.notice;
    //candata.escInit;
    //candata.bVoltage;
    //candata.feedVoltage;
    //candata.phaseCurrent;
    //candata.avarangeCurrent;
    Serial << F("Bus-Voltage: ") << static_cast < float > (candata.busVoltage) * 0.1 << 'V' << endl;
    //candata.mosfetTemp;
    Serial << endl;
    isNew = false;
  }
}

Beachte:

  • Du brauchst eine zusätzliche Lib. Steht drin, wo Du die bekommst.
  • Der Serialle Monitor ist schneller eingestellt.
  • Solltest Du mehr Werte sehen wollen, das Muster einfach übernehmen.
    Alle Sekunde sollte irgendwas auf genau dem zu sehen sein.

WOW @my_xy_projekt das funktioniert.
Erst einmal vielen Dank, das ist ja krass...
Darf ich Dich fragen, wie lange es dauert für Dich, so etwas zu programmieren?
Ich bin ehrlich, für mich wäre das unmöglich gewesen.
Vielen vielen Dank Dir.

Ich werde dann die Tage mal das System wirklich zusammen bauen und dann "live" Daten anschauen. Danach melde ich mich sicher wieder.

Ich danke Dir und auch Euch für den Support :slight_smile: tolles Forum, in diesem Sinne eine schönen Freitag und langes Wochenende bald.

:slight_smile:
Es ist gut, wenn ein Plan funktioniert...
Das war nur ein Schnellschuß.
Keine Ahnung, wie lange ich dafür gebraucht habe.
/edit: vermutlich ne Stunde mit Theorieüberlegung. 19:30 hab ich in nem anderen Thread den Code fertig gehabt. Aber wie gesagt, das kopieren und zwischen Doku und Code Fenster wechseln braucht mehr Zeit als alles andere.

Ist keine Raketenwissenschaft. Ich schreib auf nem Netbook, bzw. Minilaptop. Das ist die größere Schwierigkeit, weil ständig gescrollt udn Fenster gewechselt werden muß :joy:

Der Code ist auch noch nicht so richtig schick.
Normalerweise gehört für ``ìsNew```noch eine Prüfung der empfangenen Daten mit den bereits vorhandenen Daten dazu, um bei einer Änderung diese sofort zu bekommen.
Vorbereitet ist es schon, aber ich wollt einfach mal zeigen, dass es gar nicht so schwer ist an die Daten zu kommen.

Gibt es zu der Doku noch mehr? Denn für 3 Werte gibt es ein Bitpattern, was irgendwo dokumentiert sein muss, damit man zu den Bits die passenden Meldungen für Error, Warning und Notice in Klartext dekodieren kann. (Paket 4 und 5)

Sag einfach Bescheid, was Du brauchst, ich friemel Dir da alles raus, was geht.

/edit2: Noch für das Btpattern die richtigen Elemente eingetragen.... Du musst den Code also nochmal holen.

Hi,
ja gibt noch eine dedizierte Fehlerliste, die muss ich suchen. Ist dann genau aufgezeigt welche Bytes zusammen welchen Fehler ergeben.
Habe soeben versucht das Display ST7789 anzuschliessen, aber leider ist der UNO zu schwach für die Lib. Denke ich werde in Ruhe auch erneut alles auf den Teensy transferieren. Der packt einfach ein Vielfaches mehr.
Ich melde mich heute Abend wieder mit der Fehlerliste (hoffe ich finde sie in meinem "gut organisierten" Chaos).
Ich muss ehrlich sagen, dass ich Deinem Code wenigstens folgen kann, sprich ich konnte verstehen, wie Du was zusammenbringst, wo Du was ausliest und so weiter. Ich finde den Code sehr ordentlich, als Laie verständlich.

1 Like

Wie groß is'n der? (Pixel x Pixel)
Normalerweise sollte der UNO mit dem umgehen können und das bissl CAN-Geraffel sollte da nix weiter ausmachen.

Kannst Du bitte die Library und einen Link zum tatsächlich verwendeten Display angeben?

7789 ist etwas exotisch, jedenfalls scheint die famose U8G2 von Oli Kraus den nicht direkt zu unterstützen. OLED in 128x64, -x128, -x160 sollten eigentlich am Uno kein wirkliches Problem darstellen.

Ich hab mal was gebaut.
Der passt super in einen UNO.

Der Sketch verwendet 18850 Bytes (58%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 755 Bytes (36%) des dynamischen Speichers, 1293 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Library ist notwendig, solltest aber finden :slight_smile:
HInweis: Normalerweise sollte bei der Installation der 7789-Lib der notwendige Rest mitinstalliert werden.

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <mcp_can.h>
#include <SPI.h>
#include <Streaming.h>     // https://github.com/janelia-arduino/Streaming

constexpr uint8_t TFT_DC {9};
constexpr uint8_t TFT_RST {8};
constexpr uint8_t TFT_CS {7};

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];              // Array to store serial string

constexpr uint8_t CAN0_CS {10};   // Set CS to pin
MCP_CAN CAN0(CAN0_CS);

constexpr uint8_t CAN0_INT {2};   // Set INT to pin

struct CANDATA
{
  uint16_t batVoltage;
  uint16_t batCurrent;
  int32_t rpm;
  int16_t motoTemp;
  int16_t escTemp;
  int16_t externTemp;
  int16_t pwmOut;
  int16_t pwmIn;
  uint32_t error;
  uint32_t warning;
  uint32_t notice;
  uint16_t escInit;
  uint16_t bVoltage;
  uint16_t feedVoltage;
  uint16_t phaseCurrent;
  uint16_t avarangeCurrent;
  uint8_t busVoltage;
  uint8_t mosfetTemp;
};

CANDATA candata;
CANDATA olddata;

bool isNew;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start...."));
  tft.init(240, 240);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextWrap(true);
  tft.print(F("Start"));

  for (byte b = 0; b < 4; b++)
  {
    delay(100);
    tft.print('.');
  }

  delay(200);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
  { Serial.println(F("MCP2515 Initialized Successfully!")); }
  else
  { Serial.println(F("Error Initializing MCP2515...")); }

  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.
  pinMode(CAN0_INT, INPUT);                     // Configuring pin for /INT input
}

void loop()
{
  canRead();
  displayData();
}

void canRead()
{
  if (!digitalRead(CAN0_INT))                        // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)

    if ((rxId & 0x80000000) == 0x80000000)    // Determine if ID is standard (11 bits) or extended (29 bits)
    { sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len); }
    else
    { sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len); }

    Serial.print(msgString);

    if ((rxId & 0x40000000) == 0x40000000)    // Determine if message is a remote request frame.
    {
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    }
    else
    { splitCanMsg(); }

    Serial.println();
  }
}

void splitCanMsg()
{
  switch (rxId)
  {
    case 0x001:
      /*
        0x54 0x00           // [unsigned] Battery Voltage *0,1V    (8,4V)
        0x00 0x00           // [unsigned] Battery Current *0,1A
        0x00 0x00 0x00 0x00 // [signed] RPM
      */
      candata.batVoltage = rxBuf[0] | rxBuf[1];
      candata.batCurrent = rxBuf[2] | rxBuf[3];
      candata.rpm = rxBuf[4];
      candata.rpm += static_cast < uint32_t > (rxBuf[5]) << 8;
      candata.rpm += static_cast < uint32_t > (rxBuf[6]) << 16;
      candata.rpm += static_cast < uint32_t > (rxBuf[7]) << 24;
      break;

    case 0x002:
      /*
        0x00 0x00           // [signed] Motor Temp *1°C
        0x00 0x00           // [signed] ESC Temp *1°C
        0x00 0x00           // Reserved
        0x00 0x00           // [signed] Wenn ein externer Sensor verbaut ist *1°C
      */
      candata.motoTemp = rxBuf[0] | rxBuf[1];
      candata.escTemp = rxBuf[2] | rxBuf[3];
      candata.externTemp = rxBuf[6] | rxBuf[7];
      break;

    case 0x003:
      /*
        0x00 0x00           // [signed] Output PWM
        0x00 0x00           // [signed] Input PWM
      */
      candata.pwmOut = rxBuf[0] | rxBuf[1];
      candata.pwmIn = rxBuf[2] | rxBuf[3];
      break;

    case 0x004:
      /*
        0x00 0x00 0x20 0x00 // [unsigned] ERROR  (0000 0000 0000 0000 0010 0000 0000 0000)
        0x00 0x00 0x00 0x00 // [unsigned] WARNING
      */
      candata.error = rxBuf[0];
      candata.error += static_cast < uint32_t > (rxBuf[1]) << 8;
      candata.error += static_cast < uint32_t > (rxBuf[2]) << 16;
      candata.error += static_cast < uint32_t > (rxBuf[3]) << 24;
      candata.warning = rxBuf[4];
      candata.warning += static_cast < uint32_t > (rxBuf[5]) << 8;
      candata.warning += static_cast < uint32_t > (rxBuf[6]) << 16;
      candata.warning += static_cast < uint32_t > (rxBuf[7]) << 24;
      break;

    case 0x005:
      /*
        0x00 0x00 0x00 0x20 // [unsigned] Notice (0000 0000 0000 0000 0000 0000 0010 0000
        0x00 0x00           // Reserved
        0x90 0x01           // [unsigned] ESC INIT Status          (400)
      */
      candata.notice = rxBuf[0];
      candata.notice += static_cast < uint32_t > (rxBuf[1]) << 8;
      candata.notice += static_cast < uint32_t > (rxBuf[2]) << 16;
      candata.notice += static_cast < uint32_t > (rxBuf[3]) << 24;
      candata.escInit = rxBuf[6] | rxBuf[7];;
      break;

    case 0x006:
      /*
        0x54 0x00           // [unsigned] Battery Voltage *.1V     (8,4)
        0x94 0x00           // [unsigned] Feeding Voltage *.001V   (0,148)
        0x00 0x00           // [unsigned] Max Phase Current *1A
        0x00 0x00           // [unsigned] Average Phase Current *1A
      */
      candata.bVoltage = rxBuf[0] | rxBuf[1];
      candata.feedVoltage = rxBuf[2] | rxBuf[3];
      candata.phaseCurrent = rxBuf[4] | rxBuf[5];
      candata.avarangeCurrent = rxBuf[6] | rxBuf[7];
      break;

    case 0x007:
      /*
        0x00 0x00 0x00 0x00 0x00 0x00 // Reserved
        0x77                // [unsigned] Bus Voltage *0,1V        (11,9)
        0x00                // [unsigned] Mosfet Temperature *1°C
      */
      candata.busVoltage = rxBuf[4] | rxBuf[5];
      candata.mosfetTemp = rxBuf[6] | rxBuf[7];
      break;
  }
}

void tftData()
{
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextWrap(true);
  tft.print(F("Battery Voltage: "));
  tft.print(static_cast < float > (candata.batVoltage) * 0.1);
  tft.print('V');
}

void displayData()
{
  static uint32_t lastmillis;

  if (millis() - lastmillis > 1000)
  {
    lastmillis = millis();
    isNew = true;
  }

  if (isNew)
  {
    tftData();
    Serial << F("Neuer Datensatz") << endl;
    Serial << F("Battery Voltage: ") << static_cast < float > (candata.batVoltage) * 0.1 << 'V' << endl;
    Serial << F("Battery Ampere: ") << static_cast < float > (candata.batCurrent) * 0.1 << 'A' << endl;
    Serial << F("RPM: ") << candata.rpm << "Umin" << endl;
    //candata.motoTemp;
    //candata.escTemp;
    //candata.externTemp;
    Serial << F("PWM Out: ") << static_cast < float > (candata.pwmOut) / 10.23 << '%' << endl;;
    //candata.pwmIn;
    Serial << F("ERRORDATA: ") << _BIN(candata.error) << endl;
    Serial << F("Warnings: ") << _BIN(candata.warning) << endl;
    //candata.notice;
    //candata.escInit;
    //candata.bVoltage;
    //candata.feedVoltage;
    //candata.phaseCurrent;
    //candata.avarangeCurrent;
    Serial << F("Bus-Voltage: ") << static_cast < float > (candata.busVoltage) * 0.1 << 'V' << endl;
    //candata.mosfetTemp;
    Serial << endl;
    isNew = false;
  }
}

achso: Du musst die Größe noch auf Dich ändern:
tft.init(240, 240);
und achte drauf, welche Pins ich verwendet habe.

585 flash / 36% RAM Ja sieht gut aus. Trotzdem sollte der TO mal auflisten was er insgesamt alles im Programm haben will.

Wenn da jetzt noch das dazukommt

Nicht dass es dann nach her doch eng wird.

Wie viele Symbole sind das in der Wunschausbau-Version?
Wie viele Pixel werden diese Symbole haben?
Diese Pixel wollen alle im Flash-Speicher definiert sein.

Könnte es evtl. mit Atmega 328P doch eng werden.

So aus dem Bauch heraus würde ich vermuten, dass der Teensy 4.0 recht gute Arduino-Unterstützung hat. Da es ein anderer Prozessor ist würde ich da trotzdem möglichst bald wenigstens mal mit Prozessoreinstellung Teensy 4.0 compilieren um herauszufinden ob da noch Haken sind.

Wird es nicht.

Hi Zusammen

also eigentlich nur das Display - mit den Daten. Kein Logging oder so.
Was nice wäre, wäre noch GPS mit Geschwindigkeit :wink:
Aber das ist dann ne weitere Baustelle.
Also das wäre die Antwort zur Wunschfrage: "Was alles noch".

Auf einem anderen Teensy läuft bereits der PWM Generator mit dem ST7789 Display.
Ich weiss nicht ob das Alles für einen Prozessor zu viel werden würde.
PWM plus CAN Bus zusammen. Muss heute Abend schauen, was für ein Fehler kam beim Compillieren.
Falls der Transfer auf den Teensy läuft, würde ich dann auch versuchen den PWM Part reinzukopieren und schauen ob die Performance noch stimmt.

Übrigends ich heisse Fabian, finde das wäre weniger anonym oder?
Falls ihr das auch so seht, lebe seit 15 Jahren in der Schweiz am Zürisee und gebürtig aus dem tiefsten Süden (Singen/Konstanz).

LG Fabian

1 Like

Na ist die Kristallkugel in der Spülmaschine fertig gespült?
und du hast die maximale Anzahl Symbole darin gesehen?

Symbol 64 x 64 Pixel / 8 Pixel pro byte = 512 Byte pro Symbol.

512 Byte * 30 = 15360 Byte. Willst du am Ende noch nen FRAM-Chip zum Atmega328P dazu basteln?

warum verwendet ihr denn nicht einen Teensy oder so? Der hat vom Speicher her viel mehr Reserven oder gibt es "driftige" Gründe dagegen?

Was hast Du denn nicht verstanden?

nein ich meinte eher generell oder? Oder anders herum gefragt, auf welchen Plattformen programmiert ihr?

Preis....
Und diverse Kompatibilitäten.
Es gibt viele Libs, die nur AVR laufen.

Hier läuft eine 1.8.19 Arduino IDE als portable.
Geht mit der 2 nicht.
Dafür habe ich auch eine mit dem Teensy-Framework :slight_smile:

Displays mit ST7789 sind RGB TFT mit max 320 x 240 Pixel. Es wird von Adafruit und TFT_eSpi unterstützt, gibts auch in 8Bit Ausführung für 5V

Arduino Uno / Nano / Mega
ESP8266 (ESP-01, Mini)
ESP32 (DevKit, Lolin)

(Links sind nur Beispiele).
Ich habe noch einen Teensy in irgendeiner Schublade liegen... wenn ich nur wüsste, in welcher :slight_smile:

Außerdem bewege ich mich gerade weg von den Arduino IDEs und arbeite eher mit VS Code / PlatformIO.

CAN, Display (welche Größe in Pixel?), GPS und PWM könnte dann doch eng werden auf Uno/Nano.

Gruß Walter

Hallo Zusammen

ich habe den Code hochgeladen und er läuft - wow, einfach krass.
Anbei ist noch das Manual des Reglers.
Auf Seite 56 und folgende Seiten gibt es die Fehler-Codes.
Wobei eigentlich der Regler an sich "sehr konservativ" eingestellt ist, noch :wink:
Bei dem anderen Code für den Teensy habe ich das Flackern des Displays mit Sprites eliminiert. Ist das der richtige Ansatz? Oder gibt es bessere Wege?
Das mit den Sprites hat immerhin geklappt nach langem Versuchen.
Oder liegt das an dem UNO und seiner Frequenz mit welcher er "rechnet"?
Ich hatte das Gefühl, dass der Teensy schon ein "flickering" hat aber der UNO ist deutlich langsamer....
HBCi_Global_manual_PRELIMINARY-F4.pdf (3.7 MB)

@wno158 habe ich noch nie in den Händen gehabt. Vielleicht wäre das auch eine Möglichkeit.
@my_xy_projekt das mit der fehlenden Kompatibilität kenne ich vom Teensy, das ist manchmal, vor allem als Anfänger, sehr frustrierend.