Forum: Mikrocontroller und Digitale Elektronik NODEMCU ESP32 Anemometer RS485 MAX485


von Stefanie F. (stefanie_f)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin Anfänger und muss ein Projekt umsetzen, bei dem ich einen 
Windmesser und eine Windfahne (wurden mir übergeben) mittels NodeMCU 
ESP32 auslesen soll.
Ich habe die Anleitung zum Windmesser/Anemometer angehängt.
Es kommuniziert über RS485.

Soweit ich bisher weiß, kann ich als RX 16 und TX 17 nutzen.
Ich muss eine Anfrageadresse eingeben:
"0x01, 0x03, 0x00, 0x16, 0x00, 0x01, 0x65, 0xCE" und weiß auch, an 
welcher Stelle dann die Windgeschwindigkeit ausgegeben wird in HEX.

Nun die Frage, wie ich das ganze verkable und ansteuere.

Hatte jemand ein ähnliches Projekt oder will mir auch so helfen? Das 
wäre super.

Liebe Grüße
Stefanie

: Verschoben durch Moderator
von Helmut -. (dc3yc)


Lesenswert?

Dann schreibe oder male doch mal, wie du dir das vorstellst. Wir helfen 
hier gerne, aber machen ungerne deine ganzen Hausaufgaben.
Was du brauchst, ist ein RS485-Leitungstreiber. Ich nehme an, das ist 
der MAX485 und eine Leitung zum Sensor. Abschlusswiderstände nicht 
vergessen! Und dann kannst du über die 2. serielle Schnittstelle auf 
deinem ESP mit dem Sensor kommunizieren. Achte auf die richtige Baudrate 
und das Timing RX/TX.

: Bearbeitet durch User
von Stefanie F. (stefanie_f)


Angehängte Dateien:

Lesenswert?

Da es sich um ein Bus-System handelt, habe ich ModbusMaster zur 
Bibliothek hinzugefügt von https://github.com/4-20ma/ModbusMaster

Mein Anemometer wird an 12V und GND angeschlossen und hat eine 485-A- 
und B-Leitung.

Nach der Anleitung von http://www.bizkit.ru/en/2019/02/21/12563/ habe 
ich das MAX485 (es ist ein 5V-Teil, ESP32 liefert aber nur 3.3V, habe 
aber schon mehrmals gelesen, dass das nicht stören sollte) mit dem ESP32 
und A und B des Anemometers verkabelt.
Folgenden Code habe ich dann erstmal ins Arduiono IDE reingeladen:
"#include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster
/*!
  We're using a MAX485-compatible RS485 Transceiver.
  Rx/Tx is hooked up to the hardware serial port at 'Serial'.
  The Data Enable (DE) and Receiver Enable (RE) pins are hooked up as 
follows:
*/
#define MAX485_RE_NEG  4 //D4 RS485 has a enable/disable pin to transmit 
or receive data. Arduino Digital Pin 2 = Rx/Tx 'Enable'; High to 
Transmit, Low to Receive
#define Slave_ID       1
#define RX_PIN      16 //RX2
#define TX_PIN      17  //TX2
// instantiate ModbusMaster object
ModbusMaster modbus;
void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, HIGH); //Switch to transmit data
}
void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, LOW); //Switch to receive data
}
void setup()
{
  pinMode(MAX485_RE_NEG, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, LOW);
  // Modbus communication runs at 9600 baud
  Serial.begin(9600, SERIAL_8N1);
  Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
  modbus.begin(Slave_ID, Serial2);
  // Callbacks allow us to configure the RS485 transceiver correctly
  modbus.preTransmission(preTransmission);
  modbus.postTransmission(postTransmission);
}
long lastMillis = 0;
void loop()
{
  long currentMillis = millis();
  if (currentMillis - lastMillis > 1000)
  {
    uint8_t result = modbus.readInputRegisters(0x01, 2);

    if (getResultMsg(&modbus, result))
    {
      Serial.println();
      double res_dbl = modbus.getResponseBuffer(0) / 10;
      String res = "Temperature: " + String(res_dbl) + " C\r\n";
      res_dbl = modbus.getResponseBuffer(1) / 10;
      res += "Humidity: " + String(res_dbl) + " %";
      Serial.println(res);
    }
    lastMillis = currentMillis;
  }
}
bool getResultMsg(ModbusMaster *node, uint8_t result)
{
  String tmpstr2 = "\r\n";
  switch (result)
  {
  case node->ku8MBSuccess:
    return true;
    break;
  case node->ku8MBIllegalFunction:
    tmpstr2 += "Illegal Function";
    break;
  case node->ku8MBIllegalDataAddress:
    tmpstr2 += "Illegal Data Address";
    break;
  case node->ku8MBIllegalDataValue:
    tmpstr2 += "Illegal Data Value";
    break;
  case node->ku8MBSlaveDeviceFailure:
    tmpstr2 += "Slave Device Failure";
    break;
  case node->ku8MBInvalidSlaveID:
    tmpstr2 += "Invalid Slave ID";
    break;
  case node->ku8MBInvalidFunction:
    tmpstr2 += "Invalid Function";
    break;
  case node->ku8MBResponseTimedOut:
    tmpstr2 += "Response Timed Out";
    break;
  case node->ku8MBInvalidCRC:
    tmpstr2 += "Invalid CRC";
    break;
  default:
    tmpstr2 += "Unknown error: " + String(result);
    break;
  }
  Serial.println(tmpstr2);
  return false;
}"

Der Autor hat zwar andere Sensoren angebaut, aber das stört m.E. nicht.

Nun frage ich mich, wohin ich mein Inquiry Frame hinschreiben soll. Laut 
Anleitung vom Anemometer ist das folgendermaßen:
Address Function Start Address DataLength CRC-L  CRC_H
0x01     0x03      0x00 0x16    0x00 0x01   0x65  0xCE

ich hatte das folgendermaßen eingebaut, ist aber Käse, weil Antworten 
angezeigt werden, egal ob sich das Anemometer dreht oder nicht. Siehe 
Datei.ino

Vielleicht gibts jetzt einen Tipp? ;-)

Vielen Dank schon mal

von Helmut -. (dc3yc)


Lesenswert?

Stefanie F. schrieb:
> es ist ein 5V-Teil, ESP32 liefert aber nur 3.3V

Da gehören auf jeden Fall Pegelwandler hin. Dein ESP wird's dir danken.

Jedes Mal, wenn du Daten haben willst, musst du das Inquiry Frame 
schicken und dein Sensor antwortet drauf.

von Stefanie F. (stefanie_f)


Lesenswert?

dann habe ich entweder die falsche Stelle für das Frame gewählt oder 
falsch formuliert.
Mir wird immer die selbe Antwort ausgegeben, egal, ob das Anemometer am 
Netzteil hängt oder nicht oder stillsteht oder angedreht wird. :-(

von Stefanie F. (stefanie_f)


Angehängte Dateien:

Lesenswert?

So, hier der aktuelle Code:

#include "ModbusMaster.h" //https://github.com/4-20ma/ModbusMaster

#define MAX485_RE_NEG  18 //D4 RS485 has a enable/disable pin to 
transmit or receive data. Arduino Digital Pin 2 = Rx/Tx 'Enable'; High 
to Transmit, Low to Receive
#define MAX485_DE 19
#define Slave_ID       1
#define RX_PIN      16 //RX2
#define TX_PIN      17  //TX2

// instantiate ModbusMaster object
ModbusMaster modbus;

void preTransmission()
 {
  digitalWrite(MAX485_RE_NEG, HIGH); //Switch to transmit data
  digitalWrite(MAX485_DE, HIGH);
  delay(1);
 }
void postTransmission()
 {
  delay(3);
  digitalWrite(MAX485_RE_NEG, LOW); //Switch to receive data
  digitalWrite(MAX485_DE, LOW);
 }
void setup()
 {
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  //digitalWrite(MAX485_RE_NEG, LOW);
  //digitalWrite(MAX485_DE, LOW);

  // Modbus communication runs at 9600 baud
  Serial.begin(9600);
  Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
  modbus.begin(Slave_ID, Serial2);
  // Callbacks allow us to configure the RS485 transceiver correctly

   modbus.preTransmission(preTransmission);
   modbus.postTransmission(postTransmission);
delay(1000);
}

void loop()
{
 digitalWrite(MAX485_RE_NEG, HIGH);
 preTransmission();
 byte Anemometer_request[] = {0x01, 0x03, 0x00, 0x16, 0x00, 0x01, 0x65, 
0xCE}; // inquiry frame Anemometer
 // byte Anemometer_request[] = {0x02, 0x03, 0x00, 0x17, 0x00, 0x01, 
0x34, 0xC0E}; // inquiry frame Windfahne
 Serial2.write(Anemometer_request,8);
  //Serial2.flush();
 delay(10);
 postTransmission();
 delay(100);

 byte Anemometer_buf[8];
 Serial2.readBytes(Anemometer_buf, 8);
 Serial.print("HEX : ");
  for( byte i=0; i<7; i++ ) {
    if ((Anemometer_buf[0]=(0x01)) and (Anemometer_buf[1]=(0x03)) and 
(Anemometer_buf[2]=(0x02))  )   //for Anemometer
    //if ((Anemometer_buf[0]=(0x02)) and (Anemometer_buf[1]=(0x03)) and 
(Anemometer_buf[2]=(0x02))  )   //for Anemoscope
      {
        Serial.print(Anemometer_buf[i], HEX); // this is for test only
        Serial.print(" ");
      }
                            }
 Serial.print(" ==> ");
 int Windgeschwindigkeit=Anemometer_buf[4];
 Serial.print((Windgeschwindigkeit/10.0)); // here is the result
 Serial.print(" m/s");
 Serial.println();

 if (Serial2.available()) {
   Serial.println("available");
                              }
 else Serial.println("not available");
}



Antwort wird dann so angezeigt:
12:12:55.077 -> HEX : 1 3 2 B8 44 0 0  ==> 6.80 m/s
12:12:55.153 -> not available
12:12:56.187 -> HEX : 1 3 2 44 44 0 0  ==> 6.80 m/s
12:12:56.234 -> not available

Laut Anleitung ist die Windgeschwindigkeit an Stelle 5, gezählt wird von 
0.
Nur steht das Teil.
hat jemand eine Idee?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.