Hoe werkt data communication

hoe kan ik van de 1 arduino naar de ander arduino een informatie sturen
dit moet maar in 1 richting kunnen en het zouden 3 verschuilende Strings moeten kunnen zijn

Om welke Arduinos gaat het? (Uno, Nano, Mega, ...)?

uno en uno

ik zou moet eigenlijk van af 1 uno de 3 Strings naar 3 uno en 1 mega moeten kunnen sturen maar die moet niet kunnen terug praten

Voor Uno naar Uno heb je twee mogelijkheden

  1. Tx van Uno1 (deze praat) met Rx van Uno2 (deze luistert) verbinden. Nadeel is aansluiting op Tx en Rx het laden van het programma vanuit de IDE beinvloedt dus moet jet het iedere keer los halen.
  2. Gebruik van SoftwareSerial (of een van de alternatieven zoals AltSoftSerial). Zie bv https://docs.arduino.cc/learn/built-in-libraries/software-serial. Nadeel is dat de baudrate beperkt is to max 38400 (19200 is een veilig maximum).

Voor Uno naar Mega of omgekeerd zou je op de Mega een van de extra seriele poorten kunnen gebruiken.

RS485 gebruiken (met MAX485 voor 5V of MAX3485 voor 3V3). De master, hier de zendende UNO, kan zo een broadcast doen naar meerdere slaves. Als er inderdaad maar in 1 richting wordt gezonden, dan kunnen pennen 2 en 3 vast aan VCC. Wel zorgen voor een correcte afsluiting met 120Ω aan beide uiteinden.

Mogelijk kan je met 1 string al verder als je JSON gebruikt. Elke slave kan er dan de data uithalen die het nodig heeft. Je kan elke node een adres geven.

dus met SoftwareSerial kan ik niet naar meerder slave praten

(met MAX485 voor 5V of MAX3485 voor 3V3)
is er nog een verschil buiten de volts

SoftwareSerial is een softwarematige UART. Deze emuleert RS232 TTL. RS232 stamt uit het telex tijdperk en is full duplex peer to peer bedoeld. In het Nederlands gezegd het is gemaakt om 2 apparaten in beide richtingen met elkaar te laten 'praten'. Dit over niet zo een grote lengte. Afhankelijk van bekabeling, als dan niet getwist, afgeschermd of niet, storingen van buiten uit. De spanning onder een bepaald niveau worden aanzien als een 1 en boven een niveau als een 0.

RS485 is een half duplex (of RS422 voor full duplex) industriële standaard waar 1 master kan communiceren met meerdere klanten (standaard tot 32). In de industrie ook wel MOD bus genoemd. Dit kan over meerdere 100 meter verlopen. RS485 is ook veel minder storing gevoelig. Net als ethernet is RS485 differentieel. Dat wil zeggen dat de polariteit van de uitgangen wisselt om een 0 of 1 weer te geven. Voorbeeld A > B met >=200mV RO = 1. A < B met >= 200mV, RO = 0. Je TX pin aan pin 4 DI voor de zender. RX heb je daar niet nodig. Aan ontvangst zijde RX pin aan pin 1 RO.

Aan RS485 zijde zijn beiden gelijk. Uiteraard zijn ze pin compatibel. MAX485 heeft een absolute maximum spanning van 12V, bij de MAX3485 is dat 7V. De MAX3485 zal waarschijnlijk wel een tijd goed werken op 5V. Maar is daar zeker niet voor gemaakt.

Nog een toevoeging. Het gebruik van hardware serial heeft altijd de voorkeur op software serial. Heeft het gebruikte IC extra hardware serial poorten kan je die best gebruiken om de MAX(3)485 van data te voorzien. Je kan echter de hardware serial niet gebruiken als USB monitor en gelijktijdig voor de RS485 verbinding. Dan zal de RS485 via software serial moeten verlopen.

De eerste vraag die we moeten stellen is over welke afstanden we praten. Als die Arduinos naast elkaar liggen heb je geen RS232/RS485 nodig; het gaat hier om de fysieke layer (de verbinding tussen je Arduinos). Dit (engelstalige) artikel kan wat inzicht geven in wat je nodig hebt: The main differences between RS-232, RS-422 and RS-485.

De fysieke layer is niet relevant als het aankomt op wat de processor doet (1); de processor heeft een UART (een stukje hardware) die de data over de seriële poort stuurt; je schrijft data naar de UART en die zet het om in een (seriële) stroom van bits. Aan de andere kant wordt die stroom van bits weer omgezet zodat de processor deze verder kan gebruiken.

Nu heeft een 328P gebaseerde Arduino (bv je Uno of een klassieke Nano) slechts één hardware UART en die wordt ook gebruikt voor de communicatie met de PC. Dus als je zowel met een PC als met een andere Arduino wilt communieren heb je een probleem. Daarom zijn er software implementaties die de UART simuleren.

Dat kun je wel; je kunt de Tx(2) pin van een Arduino aansluiten op de Rx(2) pin van drie andere Arduinos en op die manier data van één Arduino naar drie andere Arduinos sturen.

De fysieke layer maakt verder niet uit.


(1) Als je bidirectionele communicatie via RS485 nodig hebt moet de software op de processor iets meer doen om ontvangst en zenden in- en uit te schakelen. Dit geldt in jouw geval niet.
(2) Tx en Rx zijn hier niet noodzakelijkerwijs de pinnen die gemarkeerd zijn met Tx en Rx; het kunnen in het geval van SoftwareSerial enige twee pinnen zijn.

ze staan naast mekaar

hij geeft op de laatste regel een foutmelding weet u waarom

#include <Keypad.h>
#include <SoftwareSerial.h>
const byte rxPin = 0;
const byte txPin = 1;
SoftwareSerial mySerial (rxPin, txPin);
byte Password_Length = 6;
byte data_count = 0;
byte data_count1 = 0;
byte data_count2 = 0;
String Data;
String Data1;
String Data2;
String Data3;
byte data3;
String A;
String B;
String C;
int opslaga = 0;
int opslagb = 0;
int opslagc = 0;
int opslagd = 0;
int opslage = 0;
int opslagf = 0;
long a;
long b;
long c;
long d;
long e;
long f;
const byte ROWS = 4;
const byte COLS = 3;
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', },
  {'4', '5', '6', },
  {'7', '8', '9', },
  {'*', '0', '#', }
};
byte colPins[ROWS] = {9, 8, 7, 6};
byte rowPins[COLS] = {13, 12, 11, };
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
void setup() {
  Serial.begin(9600);
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
    
}

void loop() {
  char customKey;
  customKey = customKeypad.getKey();

  if (customKey ) {
    if (Data2 == "*") {
      if (data_count < 6) {
        Data += customKey;
        data_count++;
      }
      if (data_count == 6) {
        Data1 += customKey;
        data_count1++;

      }
    }
    if (Data2 == "#") {
      Data3 += customKey;
      data_count1 += 6;
    }

    if (data_count2 == 0) {
      Data2 += customKey;
      data_count2++;
    }
  }

  if (data_count1 == Password_Length ) {
    if (Data2 == "*") {
      verdellen();
    }
    if (Data2 == "#") {
      afladen();
    }
    clearData();
  }
}

void clearData() {
  data_count = 0;
  Data = "";
  data_count1 = 0;
  Data1 = "";
  data_count2 = 0;
  Data2 = "";
  Data3 = "";
  data3 = 0;
}
void printdata() {
  Serial.print("code is=");
  Serial.print(Data);
  delay(10);
  Serial.print(Data1);
  delay(10);
  Serial.print("; code 2 is=");
  Serial.print(Data3);
  delay(10);
  Serial.print("; soorteer code=");
  Serial.print(Data2);
  delay(10);
  Serial.print("; oplsaga=");
  Serial.print(opslaga);
  delay(10);
  Serial.print("; oplsagb=");
  Serial.print(opslagb);
  delay(10);
  Serial.print("; oplsagc=");
  Serial.print(opslagc);
  delay(10);
  Serial.print("; oplsagd=");
  Serial.print(opslagd);
  delay(10);
  Serial.print("; oplsage=");
  Serial.print(opslage);
  delay(10);
  Serial.print("; oplsagf=");
  Serial.print(opslagf); 
}
void verdellen() {
  functie();
  functie2();
  printdata();
  clearData();
}
void afladen() {
  functie3();
  dataportaal();
  printdata();
  clearData();
}
void functie() {
  a = Data.toInt() / 10000;
  b = Data.toInt() / 100 ;
  c = Data.toInt() ;
  d = Data1.toInt() / 10000;
  e = Data1.toInt() / 100;
  f = Data1.toInt() ;
  c -= b * 100;
  b -= a * 100;
  f -= e * 100;
  e -= d * 100;
}
void functie2() {
  if (opslaga >= a and opslagb >= b and opslagc >= c and opslagd >= d and opslage >= e and opslagf >= f ) {
    opslaga -= a;
    opslagb -= b;
    opslagc -= c;
    opslagd -= d;
    opslage -= e;
    opslagf -= f;
    datamega();

  }
  else {
    inwacht();
  }
}
void inwacht() {
  printdata();
  if (a < 10) {
    A += 0;
  }
  A += a;
  if (b < 10) {
    A += 0;
  }
  A += b;
  if (c < 10) {
    A += 0;
  }
  A += c;
  if (d < 10) {
    B += 0;
  }
  B += d;
  if (e < 10) {
    B += 0;
  }
  B += e;
  if (f < 10) {
    B += 0;
  }
  B += f;
}
void  functie3()  {
  data3 = Data3.toInt();
  if (data3 == 1) {
    opslaga += 36;

  }
  if (data3 == 2) {
    opslagb += 36;
  }
  if (data3 == 3) {
    opslagc += 36;
  }
  if (data3 == 4) {
    opslagd += 36;
  }
  if (data3 == 5) {
    opslage += 36;
  }
  if (data3 == 6) {
    opslagf += 36;
  }
  dataportaal();
  printdata();
  clearData();
}
void  datamega() {

}
void  dataportaal() {
  mySerial.write(Data3);

}

Dat het KAN is nog niet hetzelfde als het is good practice. De kans is niet denkbeeldig dat je een mooie GND lus gaat creëren. En dan komen we weer tot onverklaarbare fenomenen. Een MAX485 in DIL kost amper 3,61€ + verzending. Een BOB kost zelfs maar 1,12€. Maar ik vermoed dat je daar op enkele bordjes de 120Ω weerstandjes moet verwijderen. Bij het parallel schakelen van de verschillende ingangen ga je ook de individuele capaciteiten optellen. Dit komt de steilheid van het signaal zeker niet ten goede.

heeft u een vb code van een MAX483

Welk voorbeeld wil je? Hoe stuur ik de MAX485 aan? Hoe verzend ik een boodschap? Hoe ontvang ik die boodschap?

Als kan van hoe je iets verzend en hoe je iets ontvangt

#include <avr/wdt.h>
#include <ArduinoJson.h>

const uint8_t BROADCAST_ADRES = 255;
const uint8_t ADRES = 2;

// serial variabelen en constanten
const uint16_t BaudRate = 4800;
const byte numChars = 50;
char receivedChars[numChars];
boolean newData = false;

#define LED 1

void decodeJSon(String payload);
void recvWithStartEndMarkers();
void showNewData();

void decodeJSon(char *payload) {
  String sKey;
  String waarde;
  String sPost;
  float fltWaarde;
  uint8_t ubtWaarde;
  int8_t btWaarde;

  String strLading;
  boolean flgBroadcast = false;
  boolean flgAdres = false;

  DynamicJsonDocument root(100);
  DeserializationError fout = deserializeJson(root, payload);
  JsonObject result = root.as<JsonObject>();

  for (JsonObject::iterator it = result.begin(); it != result.end(); ++it) {
    sKey = it->key().c_str();
    //sendRs485(sKey);
    if (sKey.equalsIgnoreCase("Adres")) {
      // voorbeeld {"Adres":2}
      ubtWaarde = result[sKey].as<byte>();
      if (ubtWaarde == ADRES) {
        flgAdres = true;
      }
      // broadcast adres = 255
      else if (ubtWaarde == BROADCAST_ADRES) {
        flgBroadcast = true;
      }
    }
    if (flgAdres || flgBroadcast) {
      if (sKey.equalsIgnoreCase("Led")) {
        // voorbeeld {"Adres":2, "Led": "Aan"}
        waarde = result[sKey].as<String>();
        //Serial.print("Functie? ");
        if (waarde.equalsIgnoreCase("Aan")) {
          digitalWrite(LED, HIGH);
        } else {
          digitalWrite(LED, LOW);
        }
      }
    }
  }
}

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 1;
  char startMarker = '{';
  char endMarker = '\n';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (recvInProgress) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      } else {
        receivedChars[ndx] = '\0';  // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
      receivedChars[0] = '{';
      ndx = 1;
    }
  }
}

void showNewData() {
  if (newData == true) {    
    decodeJSon(receivedChars);
    newData = false;
  }
}

void setup() {
  //Serial.begin(BaudRate);
  Serial.begin(19200);
  // setup diverse IO
  // RS485 uitgang, hoog bij verzenden.
  //pinMode(RS485Out, OUTPUT);// niet gebruikt om te ontvangen
  pinMode(LED, OUTPUT);
  wdt_enable(WDTO_4S);
}

void loop() {
  wdt_reset();
  recvWithStartEndMarkers();
  showNewData();
}

Ontvangen. Voor software serial dien je de nodige zaken toe te voegen. Kijk ook de juiste poort na voor de led.

Uiteraard dient dit ook aangepast aan de software serial

while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

De led zou moeten knipperen indien het adres juist is (hier 2) en het broadcast adres (255) wordt gebruikt.

#include <avr/wdt.h>
#include <ArduinoJson.h>

void sendRs485(String payload);

void postJson(uint8_t adres, bool flg);

const uint16_t BaudRate = 19200;
// output poort maakt het verzenden van RS485 boodschappen mogelijk. (Half duplex)
#define RS485Out 5

void sendRs485(String payload) {
  digitalWrite(RS485Out, HIGH);  // RS485 in verzendmodus brengen. Kan vervallen als je de beide ingangen 2 en 3 van de MAX485 hoog maakt (aan VCC)
  Serial.println(payload);
  Serial.flush();
  digitalWrite(RS485Out, LOW);  // RS485 terug in ontvangstmodus idem als openen
}

void postJson(uint8_t adres, bool flg) {
  StaticJsonDocument<120> doc;
  doc["Adres"] = adres;
  doc["Led"] = flg;
  char json[120];  
  serializeJson(doc, json);
  sendRs485(json);
}

void setup() {
  Serial.begin(BaudRate);
  pinMode(RS485Out, OUTPUT);
  wdt_enable(WDTO_4S);
}

void loop() {
  wdt_reset();
  postJson(1, true);
  delay(1000);
  postJson(1, false);
  delay(1000);
  postJson(2, true);
  delay(1000);
  postJson(2, false);
  delay(1000);
  postJson(3, true);
  delay(1000);
  postJson(3, false);
  delay(1000);
  postJson(4, true);
  delay(1000);
  postJson(4, false);
  delay(1000);
  postJson(255, true); // broadcast adres
  delay(1000);
  postJson(255, false);
  delay(1000);
}

Eenvoudige 'zender'. Leds mogen bij de ontvanger alleen aan als het adres klopt of het broadcast adres wordt gebruikt.

bedankt
maar ik nog een paar vragen stel ik wil een String van de en naar de ander wat moet ik dan doen

Aan ontvangstzijde zijn de startmarker en de endmarker belangrijk. Elke string dat je verzend moet dus beiden hebben. Uiteraard kan je beiden wijzigen maar \n is een zogenaamd escape karakter en staat voor een nieuwe lijn of ASCII 13.

Aan zender zijde is het gewoon de string doorgeven aan

Die doet dan het nodige. Uiteraard ook hier de Serial.println aanpassen als je een andere Seriële poort of Software Serial gebruikt.

Het handigste is gebruik te maken van Json. Dit is in vele talen ondersteund. Er is wel een opstapje om het je eigen te maken maar eens je het door hebt kan je het ook gebruiken met MQTT, websockets of een gehele webpagina. Bijvoorbeeld deze link is niks anders dan Json. Ook OpenWeather gebruikt Json om gegevens te delen. De kans is dus reëel dat je er mee te maken krijgt.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.