RS485 Protocol - falscher variablen-typ

Hallo zusammen,

gerade will ich zwischen zwei Atmega328P-PU über MAX487-Bausteine eine Kommunikation aufbauen.
Ich nutze dafür diese Vorlage: Gammon Forum : Electronics : Microprocessors : RS485 communications

Allerdings bekomm ich beim Kompilieren immer einen Fehler:
(im orangen Kasten:)
"invalid conversion form ‘byte’ to ‘const bate*’
(im schwarzen Kasten:)
“In function ‘void loop()’:
error: invalied conversion from ‘byte’ to ‘const byte*’
error: initializing argument 2 of ‘void sendMsg(void ()(byte), const byte, byte)’
error: invalid conversion from ‘byte’ to ‘byte*’
error: initializing argument 3 of ‘byte recvMsg(int ()(), int ()(), byte*, byte, lang unsigned int)’”

Der Sketch:

#include <RS485_protocol.h>
#include <SoftwareSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 9;

SoftwareSerial rs485(2, 3);

void fWrite (const byte what)
{
 rs485.write (what); 
}

int fAvailable()
{
  return rs485.available();
}

int fRead()
{
  return rs485.read();
}

void setup()
{
  rs485.begin (288000);
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);
}

void loop()
{
  if (digitalRead(8) == LOW)
  {
    const byte msg = 1;
    digitalWrite(ENABLE_PIN, HIGH);
    sendMsg (fWrite, msg, sizeof msg);
    digitalWrite(ENABLE_PIN, LOW);
   
    delay(1000);
    byte buf;
    byte received = recvMsg (fAvailable, fRead, buf, 1);
   
    if (buf == 1)
    {
      digitalWrite(9, HIGH);
      delay(1000);
      digitalWrite(9, LOW);
    }
  }
}

Und gelb hervorgehoben wird immer die Zeile

sendMsg (fWrite, msg, sizeof msg);

Ich hab keine Ahnung, wie das das beheben kann, hab schon versucht, die variablen auch auf const zu setzen, irgendwie hat nichts geholfen.

LG

Fipsi

Was ist "fWrite"???
Grüße Uwe

uwefed:
Was ist "fWrite"???
Grüße Uwe

void fWrite (const byte what)
{
 rs485.write (what);
}

Ganz am Anfang.

LG

Fipsi

error: initializing argument 2 of 'void sendMsg(void ()(byte), const byte, byte)'

Heisst auf deutsch:
Das 2. Argument von sendMsg muss ein const byte * sein.

byte* und byte ist ein ganz gewaltiger Unterschied.
Das erste ist ein Pointer = eine Adresse = der Anfang eines Arrays
Welche Nachricht willst du denn senden ?

Sowas ginge:

    const byte msg[] = "Hallo";

Das ist auch falsch:
sendMsg (fWrite, msg, sizeof msg);

Wie soll das gehen? Das muss wie eine Funktion aufgerufen werden:

sizeof(msg)

Das übergibt die Länge der Nachricht

Ansonsten was Michael sagt. Obwohl die Deklaration des Arrays nicht const sein muss. sendMsg will ein Byte Array und kein Byte. Arrays sind Zeiger auf das erste Element und daher hier byte*

fWrite() ist nicht das Problem. Das ist einfach die Sende-Funktion für ein Byte. Diese wird als erster Parameter in Form eines Funktionszeigers übergeben

michael_x:

error: initializing argument 2 of ‘void sendMsg(void ()(byte), const byte, byte)’

Heisst auf deutsch:
Das 2. Argument von sendMsg muss ein const byte * sein.

byte* und byte ist ein ganz gewaltiger Unterschied.
Das erste ist ein Pointer = eine Adresse = der Anfang eines Arrays
Welche Nachricht willst du denn senden ?

Sowas ginge:

    const byte msg[] = "Hallo";

Okay… war ja mal wieder klar, dass ich in diese Falle tappe^^.

Hab jetzt mal den Code angepasst und auch den für den Slave geschrieben:

(Master)

#include <RS485_protocol.h>
#include <SoftwareSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 9;

SoftwareSerial rs485(2, 3);

void fWrite (const byte what)
{
 rs485.write (what);  
}

int fAvailable()
{
  return rs485.available();
}

int fRead()
{
  return rs485.read();
}

void setup()
{
  rs485.begin (288000);
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);
  
  digitalWrite(9, HIGH);
  delay(500);
  digitalWrite(9, LOW);
}

void loop()
{
  if (digitalRead(8) == LOW)
  {
    delay(400);
    
    const byte msg[] = "1";
    digitalWrite(ENABLE_PIN, HIGH);
    sendMsg (fWrite, msg, sizeof (msg));
    digitalWrite(ENABLE_PIN, LOW);
    
    delay(1000);
    byte buf[10];
    byte received = recvMsg (fAvailable, fRead, buf, sizeof (buf));
    
    if (buf[0] == 1)
    {
      digitalWrite(9, HIGH);
      delay(1000);
      digitalWrite(9, LOW);
    }
  }
}

(Slave)

#include <RS485_protocol.h>
#include <SoftwareSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 9;

SoftwareSerial rs485(2, 3);

void fWrite (const byte what)
{
 rs485.write (what);  
}

int fAvailable()
{
  return rs485.available();
}

int fRead()
{
  return rs485.read();
}

void setup()
{
  rs485.begin (288000);
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  
  digitalWrite(9, HIGH);
  delay(500);
  digitalWrite(9, LOW);
}

void loop()
{
  byte buf [20];
  
  byte recevied = recvMsg (fAvailable, fRead, buf, sizeof (buf) - 1);
  
  if (recevied)
  {
    if (buf[0] == 1)
    {
      digitalWrite(9, HIGH);
      
      byte msg [] = "1";
      delay(995);
      digitalWrite(ENABLE_PIN, HIGH);
      sendMsg(fWrite, msg, sizeof (msg));
      digitalWrite(ENABLE_PIN, LOW);
      delay (5000);
      digitalWrite(9, LOW);
    }
  }
}

Kann mir jemand sagen, worans liegt, dass da nichts passiert?
Die MAX 487 sind richtig angeschlossen, mehrfach kontrolliert.

LG

Fipsi

Dir fehlen wirklich die C Grundlagen

if (buf[0] == 1)

Du sendest einen String, bzw. einen char. '1' ist NICHT 1. Siehe die ASCII Tabelle:

Wobei das in anderen Sprachen genauso ist und nicht mal C spezifisch. Du kannst auch ein Byte Array statt einen String schicken. Das ist vielleicht vernünftiger wenn du das sowieso als Zahlen interpretierst.

pinMode(8, OUTPUT);

if (digitalRead(8) == LOW)

Ist Pin 8 dein Taster ?

Dann meinst du sicher

pinMode(8, INPUT_PULLUP);

Edit: 8) => 8 )

Dafuq.. das passiert mir immer wieder.. auch in PHP facepalm

Hab jetzt '1' gemacht. Funktioniert immer noch nicht.

Hab jetzt gerade mal Read ASCII String angeschaut (http://arduino.cc/en/Tutorial/ReadASCIIString#.UyR1Fb1JSUk). Da ich bei meiner Kommunikation eh nur Zahlen hin und her schick, die auch sehr gerne als solche behandelt werden dürfen, kommt mir jetzt die Frage, ob's für das rs485 auch sowas wie Serial.parseInt(); gibt.

michael_x:

pinMode(8, OUTPUT);

if (digitalRead(8) == LOW)

Ist Pin 8 dein Taster ?

Dann meinst du sicher

pinMode(8, INPUT_PULLUP);

Edit: 8) => 8 )

Hatte das in nem anderem Thread so gesagt bekommen, wie's ich verwende und so gings auch. Werd beizeiten das dann aber auch mal probieren, Danke.

LG

Fipsi

Wieso übernimmst du nicht den Sketch 1zu1 von Nick?
Die Links die ich dir in dem anderen Thread geschickt hatte, hast du schon gelesen oder?

Was passiert wenn du den Sketch so machst:

#include <RS485_protocol.h>
#include <SoftwareSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 9;

SoftwareSerial rs485(2, 3);

void fWrite (const byte what)
{
 rs485.write (what); 
}

int fAvailable()
{
  return rs485.available();
}

int fRead()
{
  return rs485.read();
}

void setup()
{
  rs485.begin (288000);
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);
}

void loop()
{
  if (digitalRead(8) == LOW)
  {
  byte msg [] = {  1  };
    digitalWrite(ENABLE_PIN, HIGH);
    sendMsg (fWrite, msg, sizeof msg);
    digitalWrite(ENABLE_PIN, LOW);
   
    delay(1000);
     
  byte buf [10];
  byte received = recvMsg (fAvailable, fRead, buf, sizeof buf);
   
 if (buf [0] == 1)
    {
      digitalWrite(9, HIGH);
      delay(1000);
      digitalWrite(9, LOW);
    }
  }
}

Ja, den Link hab ich mir grad vorher angeschaut.

Wenn ich den Sketch so übernehm, passiert wieder nichts.. keine Ahnung warum.. ich hoff bloß, dass die MAX-IC's nicht hinüber sind. Kann, um das zu Testen, die RX/TX der Atmegas direkt verbinden oder muss wegen dem Code der MAX-IC mit dabei sein?

LG

FIpsi

Ich nach meinem Verständnis würde ich sagen, funktioniert auch ohne den MAX487. Der Master und der Slave hat ja seine Adresse nicht im MAX487 gespeichert sondern in dem UNO/MEGA/P328/AtTiny oder was auch immer man da nimmt. Der MAX487/RS485 ist ja nur dazu da, um über lange Leitungen Daten senden zu können. Es brauch kein extra Code/Lib. Einfach nur den Senden Pin auf HIGH oder LOW schalten und schon wir gesendet was gewünscht.

Achso, okay. Ich dachte jetzt eben, dass das mit dem MAX 487 nochmal codiert wird, so dass ich's am PC z. B. mitm Serial Monitor nicht auslesen kann. Also würde das dann funktionieren?

LG

Fipsi

Man sagt, studieren geht übers probieren :smiley:

So.. war jetzt ein bisschen nicht in der Lage dazu, dass ich weiter arbeiten konnte.. jetzt geht's mal wieder ran da.

Also ich hab den Code jetzt auf Serial umgeschrieben:

Master:

const byte ENABLE_PIN = 4;
const byte LED_PIN = 9;

void setup()
{
  Serial.begin (9600);
  
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);
  
  digitalWrite(9, HIGH);
  delay(500);
  digitalWrite(9, LOW);
}

void loop()
{
  if (digitalRead(8) == LOW)
  {
    digitalWrite(LED_PIN, HIGH);
    delay(400);
    digitalWrite(LED_PIN, LOW);
    
    digitalWrite(ENABLE_PIN, HIGH);
    Serial.print(1);
    digitalWrite(ENABLE_PIN, LOW);
    
    delay(1000);
    
    if (Serial.available())
    {
       int answer = Serial.read();
    
      if (answer == 1)
      {
        digitalWrite(9, HIGH);
        delay(1000);
        digitalWrite(9, LOW);
      }
    }
  }
}

Slave:

const byte ENABLE_PIN = 4;
const byte LED_PIN = 9;

void setup()
{
  Serial.begin (9600);
  
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  
  digitalWrite(9, HIGH);
  delay(500);
  digitalWrite(9, LOW);
}

void loop()
{
  if (Serial.available())
  {
    int msg = Serial.read();
    
    if (msg == 1)
    {
      digitalWrite(LED_PIN, HIGH);
      delay(999);
      digitalWrite(ENABLE_PIN, HIGH);
      Serial.print(1);
      digitalWrite(ENABLE_PIN, LOW);
      digitalWrite(LED_PIN, LOW);
    }
  }
}

Habs sowohl über die MAX 487-Bausteine versucht, als auch direkt. Wenn ich den Taster am Master drück, bricht danach die loop-Schleife sofort ab. Meistens werden nicht mal die 400 ms abgewartet, die gleich direkt auf die if-Bedingung folgt, sondern die LED leuchtet so lang, wie ich den Taster drück. Hab ich da irgendwas übersehen? Sollte doch eigentlich nicht so sein.
Und der Slave reagiert überhaupt nicht.
Hab gerade den PC an Serial angeschlossen, am Serial Monitor kommt gar nichts an und jetzt geht auch die LED nicht mehr aus...

LG

Fipsi

Hast dein Problem nun gelöst? Nutzt du Mega dazu? Funktioniert dann nur Serial.begin.

 if (Serial.available())

funktioniert bei mir auch nicht

   // see if there's incoming serial data:
   if (Serial.available() > 2) {
   char command =Serial.read();
   byte Slave =Serial.read();
   byte Slavevalue =Serial.read();
   byte returnvalue = 0;
   
    //Kommando auswerten
    switch(command) {
 case 'S':
      Serial.print("S Kommando empfangen, setze Slave ");
      Serial.print(Slave);
      Serial.print(" auf ");
      Serial.println(Slavevalue);
      pinMode(Slave,OUTPUT);
      digitalWrite(Slave,Slavevalue);

      //gesetzten wert auch zurückliefern
      returnvalue=Slavevalue;
      break;
      
 case 'R':
      returnvalue = digitalRead(Slave);
      Serial.print("R Kommando empfangen, lese Pin ");
      Serial.print(Slave);
      Serial.print(". Wert = ");
      Serial.println(returnvalue);
      break;
      
 default:
      Serial.println("Fehler, unbekanntes Kommando");    
      break;
    }//switch(command)
   }// Serial.available

Funktioniert

Hey,

nein, hab das Problem noch nicht gelöst, aber ehrlich gesagt dann auch nicht mehr sehr dahinter geklemmt. Nächste Woche werd ich wahrscheinlich die erste Platine löten und dann setzt ich mich wieder dran. Mein Fehler liegt wahrscheinlich beim Timing, das muss umbauen?

LG

Fipsi