Gelöst:Werteübergabe an Funktion

Hallo,

die Antwort ist vermutlich einfach, aber ich komme nicht drauf:
In meinem Sketch will ich an eine Funktion “send_can()” die can_id
und den dazugehörigen Datenbuffer “stmp” bzw. “dtmp” übergeben.
Die ID klappt, den Buffer kriege ich nicht hin.
Es sollen von verschiedenen ID die jeweiligen Buffer verschickt werden.
Dazu habe ich ein Array “can_id” mit mehreren (hex)IDs erstellt.
Der Sketch funktioniert bis auf die Funktion.

[code]
/* sketch fuer CAN-modul mit 8MHz quarz  MCP2515 library v1.1 von
   nano     CAN-modul                    https://github.com/Flori1989/MCP2515_lib
   5V       VCC
   GND      GND
   D10      CS
   D11      SI
   D12      SO
   D13      SCK
   D2       INT
*/
// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>
// Include the libs for DS18 sensor
#include <OneWire.h>
#include <DallasTemperature.h>

// Sensors DS18 at pin3
#define ONE_WIRE_BUS 3
// setup onewire instance
OneWire oneWire(ONE_WIRE_BUS);
// Pass reference to Dallas Temp
DallasTemperature sensors(&oneWire);

MCP_CAN CAN0(10);                                      // Set CS to pin 10

// Konstanten
const long intervall = 2000;   // sendeintervall
// Variablen
unsigned long prevMillis = 0; // speichere letzte zeit
uint8_t anzahlsensor = 0;     // DS18B20 - Anzahl
int resolution = 9;           // sensor resolution
// analoger Temperatursensor
int LM35 = A0;                

void setup()
{
  Serial.begin(115200);
  sensors.begin();
  sensors.setResolution(resolution);
  anzahlsensor = sensors.getDS18Count();
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures(); // Send the command to get temperatures
  // init can bus, baudrate: 500k, ACHTUNG: auf 8 oder 16MHz Quarz aufpassen!
  if (CAN0.begin(CAN_500KBPS, MCP_8MHz) == CAN_OK) Serial.print("can init ok!!\r\n");
  else Serial.print("Can init fail!!\r\n");
}

unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char dtmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint16_t can_id[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; // different can id's

void loop()
{
  unsigned long jetztMillis = millis();
  if (jetztMillis - prevMillis >= intervall) {
    prevMillis = jetztMillis;
      Serial.print("Sending Data...\r\n");
      read_LM35();
      read_DS18();
      // send data:  id = 0x10, standard frame, data len = 8, stmp: data buf
      //CAN0.sendMsgBuf(0x10, 0, 8, stmp);
      send_can(can_id[0], stmp);
      send_can(can_id[1], dtmp);
      sensors.requestTemperatures();
  }
} //end loop


// Funktionen
void read_LM35() {
  stmp[7] = (125 * (analogRead(LM35))) >> 8 ; // Wert berechnen, in stmp schreiben
}

void read_DS18() {
  for (uint8_t i = 0; i < anzahlsensor; i++) {
    stmp[i] = sensors.getTempCByIndex(i); // Wert lesen und in stmp schreiben
  }
}

void send_can(uint16_t i, unsigned char data[]) {
  CAN0.sendMsgBuf(can_id[i], 0, 8, data);
}

Vorher hatte ich die Funktion so:

void send_can(uint16_t i) {
  if (i == 0) {
  CAN0.sendMsgBuf(can_id[i], 0, 8, stmp);
  }
  if (i == 1) {
  CAN0.sendMsgBuf(can_id[i], 0, 8, dtmp);
  }
}

[/code]
Allerdings wollte ich die Werte an die Funktion übergeben und nicht fest reinschreiben.

Edit: Lösung siehe Seite 4

Hallo

such mal nach Array an Funktion übergeben z.B link

Heinz

Vorschlag:

using MeinArrayType = unsigned char[8];

MeinArrayType stmp {0, 0, 0, 0, 0, 0, 0, 0};
MeinArrayType dtmp {0, 0, 0, 0, 0, 0, 0, 0};

void send_can(uint16_t i, MeinArrayType &data) // per Referenz
{
  CAN0.sendMsgBuf(can_id[i], 0, 8, data);
}

Wow, sehr schnelle Antworten!

Ich hatte befürchtet daß es irgendwie über Pointer geht. Bin noch ziemlich
am Anfang des Weges...
@combie: Funktioniert leider nicht: exit status 1
'MeinArrayType' has not been declared
Ausserdem:
warning: invalid conversion from 'unsigned char (*)[8]' to 'int' [-fpermissive]

Scheint als ob "using" komplett ignoriert wird.
Ich werde dann mal den Link zum Rheinwerk Verlag durcharbeiten...

erstmal Vielen Dank!

Da du nicht zeigst, was du da tust, wirst du dir selber helfen müssen.

Rheinwerk Verlag

Das ist ein C Buch, und dazu noch eins mit vielen Fehlern.
Du verwendest allerdings C++, oder?

Aber was solls, jedem sein Himmelreich!

f91w:
Ich hatte befürchtet daß es irgendwie über Pointer geht.

Eine Referenz ist davon nicht weit weg.

f91w:
Scheint als ob "using" komplett ignoriert wird.

Plaziere using mal vor setup().

Eine Referenz ist davon nicht weit weg.

Wer Pointer kennt, nimmt lieber Referenzen.

agmue:
Eine Referenz ist davon nicht weit weg.
Plaziere using mal vor setup().

using vor setup() gibt andere Fehlermeldungen...mehr als vorher...

f91w:
using vor setup() gibt andere Fehlermeldungen...mehr als vorher...

Du hast mein volles Mitgefühl!

Einmal tippt man selber anstatt copy & paste...Tippfehler...
Kompilieren und hochladen problemlos.
Allerdings keine gesendeten Daten. Canviewer und auch die anderen
Busteilnehmer zeigen auf ihren Displays absolut nix mehr an.

Ich habe mal die Funktion etwas erweitert:

void send_can(uint16_t i, MeinArrayType &data) { // per Referenz
  if (CAN0.sendMsgBuf(can_id[i], 0, 8, data) == CAN_OK) Serial.print("Buf sent!\r\n");
  else Serial.print("Buf send failed!\r\n");
  Serial.println(can_id[i]);
  for (int k = 0; k < 8; k++)             // Print each byte of the data
    {
      if (data[k] < 0x10)                 // If data byte is less than 0x10, add a leading zero
      {
        Serial.print("0");
      }
      Serial.print(data[k], HEX);
      Serial.print(" ");
    }
    Serial.println();
}

Damit bekomme ich auf dem seriellen Monitor dies:

Buf sent!
0 ← can_id
00 00 00 00 00 00 00 17 ← Inhalt von stmp
Buf sent!
1 ← can_id
16 15 16 15 15 00 00 00 ← Inhalt von dtmp
Buf sent!
0
00 00 00 00 00 00 00 17
Buf sent!
1
16 15 16 15 15 00 00 00

Auf dem Bus ist allerdings nichts zu sehen. “CAN_OK” ist der return von sendMsg() innerhalb
von sendMsgBuf(). Das sollte dochen heißen daß die Daten erfolgreich gesendet wurden.
Welche Möglichkeiten habe ich um dem Problem auf die Spur zu kommen?

Schalt mal im seriellen Monitor die Zeitangaben ein und sieh mal das Ergebnis an.
Ich vermute Du versuchst zu schnell hintereinander zu senden.

Vielleicht hast Du auch zu viele ErrorFrames auf Deinem CAN und legst Dich damit selbst lahm. Müssen es für die Sensordaten unbedingt 500kbit sein?

Danke für die Antwort.
Die 500k habe ich so aus den examples der Library übernommen.
Im Sketch sende ich nur alle 2 sekunden - natürlich nicht mit delay().
Am Bus hängt noch ein RaspberryPi mit canviewer/canlogger. Wenn ich den
Sketch mit der Sende-Funktion lade tut sich auf dem Bus absolut nix mehr.

Ich bin leicht verwirrt.
Also: Du hast den Sketch wie im Eingangspost, aber die Sendefunktion wie in #10. Korrekt?
Die Nachrichten schaust Du Dir auf dem Raspi mit einem Logger an. Der Raspi sendet aber nix. Korrekt?
Meldet die Logger-SW irgendwelche Anomalien?

Wenn die Antworten ‘ja - ja - nein’ lauten, sollte es eigentlich ja gehen.

Übrigens muss die Sensormenge immer höchstens 8 sein - das überprüfst Du nicht, wenn Du in read_DS18() in den Array schreibst.

 anzahlsensor = sensors.getDS18Count();

Besser ist 7, weil im letzten Eintrag ja der LM35 gespeichert wird.

Ich kenne jetzt die CAN-Lib nicht, die Du verwendest. Wenn die mit OK zurückkommt wenn sie die Daten übernommen hat, die aber noch nicht versendet sind und es nur einen Puffer für die Daten gibt, dann mag es mit den beiden aufeinanderfolgenden Sendungen zu schnell sein:

     send_can(can_id[0], stmp);
      send_can(can_id[1], dtmp);

Also mal testweise eine der beiden rausnehmen.

Einen anderen Zweifel habe ich noch, was Deine CAN-IDs angeht:

send_can(can_id[0], stmp);

Du rufst die Sendefunktion mit der ID auf, benutzt die dann aber als Index in den ID-Array:

CAN0.sendMsgBuf(can_id[i], 0, 8, data)

Da greifst Du nur deshalb nicht irgendwo im Speicher zu, weil die IDs kleiner als die Arraygröße sind (0…4).

Danke fürs Antworten!

Sketch ist wie gepostet, Sendefunktion habe ich um ein paar Ausgaben erweitert
um zu sehen was los ist. RasPi hört zu und sagt nix.

Die Sensormenge habe ich nicht abgefragt weil ich weniger als 8 Stück habe.
Ich wollte zuerst was am Laufen haben, komplizierter kann man es immer
noch machen. Übrigens werden die Werte von DS18 und LM35 in 2 verschiedenen
Arrays gespeichert(stmp/dtmp).

Vorher hatte ich den CAN0.sendMsgBuf() mit seinen Parametern 2-mal hinter-
einander mit den jeweiligen Werten geschrieben. Hat prima funktioniert.
Zu jeder can id das entsprechende Array.

Vorher hatte ich eine einfache Funktion die nur die can_id übergeben bekommt
und stmp/dtmp fest eingebaut hat. Hat funktioniert, aber die Funktion sollte auch
den jeweiligen Datenpuffer zu jeder id übergeben bekommen.

Damit fingen die Probleme an...

Hier die ursprüngliche Form der Sendefunktion:

void send_can(uint16_t i) {
  if (i == 0) {
  CAN0.sendMsgBuf(can_id[i], 0, 8, stmp);
  }
  if (i == 1) {
  CAN0.sendMsgBuf(can_id[i], 0, 8, dtmp);
  }
}

Das klappt, ich kann beide id mit ihren Daten im canviewer auf dem Rapi sehen.
Ebenso auf den LCD an den beiden Nanos(meine Testclients).

Das ist ja im Prinzip Jacke wie Hose - Du musst Dich nur für einen Weg entscheiden:

// Übergabe der CAN-ID
      send_can(can_id[0], stmp);
      send_can(can_id[1], dtmp);
...
void send_can(uint16_t i, MeinArrayType &data) { // per Referenz
  if (CAN0.sendMsgBuf(i, 0, 8, data) == CAN_OK) Serial.print("Buf sent!\r\n");
  else Serial.print("Buf send failed!\r\n");
// Übergabe des Index in den CAN-ID-Array
      send_can(0, stmp);
      send_can(1, dtmp);
...
void send_can(uint16_t i, MeinArrayType &data) { // per Referenz
  if (CAN0.sendMsgBuf(can_id[i], 0, 8, data) == CAN_OK) Serial.print("Buf sent!\r\n");
  else Serial.print("Buf send failed!\r\n");

Übrigens werden die Werte von DS18 und LM35 in 2 verschiedenen
Arrays gespeichert(stmp/dtmp).

Nein. In beiden Funktionen steht stmp.

// Funktionen
void read_LM35() {
  stmp[7] = (125 * (analogRead(LM35))) >> 8 ; // Wert berechnen, in stmp schreiben
}

void read_DS18() {
  for (uint8_t i = 0; i < anzahlsensor; i++) {
    stmp[i] = sensors.getTempCByIndex(i); // Wert lesen und in stmp schreiben
  }
}

wno158:
Nein. In beiden Funktionen steht stmp.

Ups...das hatte ich wohl gepostet bevor ich den Tippfehler gefunden hatte...
Die id-Übergabe habe ich korrigiert, immer noch keine Daten zu sehen.

Okay.
Dann müssen wir weitersuchen.

Es könnte - sollte aber nicht - sein, dass die sendMsgBuf()-Methode mit dem übergebenen “MeinArrayType” nicht klarkommt.
1a) Hast Du alle Warnings/Fehlermeldungen in den Einstellungen aktiviert?
1b) Gibt es an der Stelle eine Warnung?

  1. Machst Du einen Test für C+±Laien wie mich?
void send_can(uint16_t i, MeinArrayType &data) { // per Referenz

  unsigned char tempData[8];
  for (int cnt = 0; cnt < 8; cnt++)
  {
    tempData[cnt] = data[cnt];
  }

  if (CAN0.sendMsgBuf(i, 0, 8, tempData) == CAN_OK) Serial.print("Buf sent!\r\n");
  else Serial.print("Buf send failed!\r\n");
}

Das wäre ja keine schöne Lösung; vielleicht würde es auch ein passender cast tun. Aber wenn auch das nicht geht, könnte ich nur noch auf die C-Lösung mit Pointer zurückgreifen.

wno158:
Okay.
Dann müssen wir weitersuchen.

Es könnte - sollte aber nicht - sein, dass die sendMsgBuf()-Methode mit dem übergebenen "MeinArrayType" nicht klarkommt.
1a) Hast Du alle Warnings/Fehlermeldungen in den Einstellungen aktiviert?
1b) Gibt es an der Stelle eine Warnung?

  1. Machst Du einen Test für C++-Laien wie mich?

1a. alles aktiviert
1b. keine Warnungen, kompiliert/lädt hoch/keine Anzeige...
2. done; Ergebnis siehe 1b.
3. Ich glaube ich bin der grössere Laie von uns beiden
Trotzdem Danke für Deine Hilfe!

f91w:
... immer noch keine Daten zu sehen.

Wo eigentlich? Habe ich überlesen, wo Du das hinschickst?

Hat das schon mal funktioniert?

Hast Du schon mal einen zweiten Arduino in den CAN-Bus zum Mitlesen gehängt und dann zwischen funktionierender und nicht funktionierender Version verglichen?

Nebenbei: Es gibt eine neuere Variante der Bibliothek: GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library