Stránka 1 z 2

Arduino UNO "MODBUS"

Napsal: 23 říj 2016, 21:09
od radekzela
Přátelé potřebuji radu.
Ano nehodí se to jako průmyslové využití ale to teď neřešme.
Jedná se mi o to. Potřebuji rozjed HMI panel a arduino po rs485 s protokolem modbus rtu. drtím se stím už tři dny ale arduino vůbec neumím.
Pevodník který chci použít je MAX485
http://arduino-shop.cz/arduino/985-prevodnik-ttl-na-rs-485-1427700037.html

V arduinu budou registry na 8 relatek 1,2,3,4,5,6,7,8
Dále regist pro 4 digitalní vstupy 10001,10002,10003,10004
Dále tam potřebuji registr 2 analogove vstupy 30001,30002
A naposled regist 40001 na ultrazvukový senzor.

Už jsme daly dohromady kód který funguje skvěle přes USB v arduinu a simulatorem HMI panelu.
Takto nám to funguje na simulatoru uplně dokonale.
https://www.youtube.com/watch?v=RVCe_gXpAxI

Na převodníku to ale nefunguje vůbec je to asi tím že nemáme definovaný pin na arduinu který se stará o přepínání odesílání a přijímání paketů.
https://www.youtube.com/watch?v=JWPuOrG4poQ


Dokonce když propojím HMI s arduinem přes převodník tak se nic neděje data prolezou ale jen chvilkově když do toho zapnu simulator v PC-arduino ale HMI-arduino se neustale odpojuje a připojuje to není to správné řešení.

Proto žádám někoho o pomoc zda by dokázal v kódu který je níže ošetřit tu komunikaci pomocí RS485 HALF-DUPLEX (převodník MAX485)

Použité knihovny: https://code.google.com/archive/p/arduino-modbus-slave/downloads


Kód: Vybrat vše

#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>

//deklarování pinů relé karty
int rele1 = 4;
int rele2 = 5;
int rele3 = 6;
int rele4 = 7;
int rele5 = 8;
int rele6 = 9;
int rele7 = 10;
int rele8 = 11;

int ECHO = 12; // Echo pin z HC-SC04 na pinu 2
int TRIG = 13; // Trig pin z HC-SC04 na pin 3

//Setup the brewtrollers register bank
//All of the data accumulated will be stored here
modbusDevice regBank;
//Create the modbus slave protocol handler
modbusSlave slave;

void setup(){   

  Serial.begin(9600);

 
  //Assign the modbus device ID. 
  regBank.setId(1);

  regBank.add(1);
  regBank.add(2);
  regBank.add(3);
  regBank.add(4);
  regBank.add(5);
  regBank.add(6);
  regBank.add(7);
  regBank.add(8);

  regBank.add(30001);   //regist pro teplotni senzor A0
  regBank.add(30002);   //regist pro teplotni senzor A1
  regBank.add(40020);   //registr pro data z ultrazvuku

  slave._device = &regBank; 

  //inicializace sériového portu s rychlostí 9600
  slave.setBaud(9600);
 
  pinMode(rele1, OUTPUT);
  pinMode(rele2, OUTPUT);
  pinMode(rele3, OUTPUT);
  pinMode(rele4, OUTPUT);
  pinMode(rele5, OUTPUT);
  pinMode(rele6, OUTPUT);
  pinMode(rele7, OUTPUT);
  pinMode(rele8, OUTPUT);

 
  //Nastaví pin 12 jako vstupní
  pinMode(ECHO, INPUT);
  //Nastaví pin 13 jako výstupní
  pinMode(TRIG, OUTPUT);
}

void loop(){
 
  unsigned long cas = millis();
  while(millis() - cas < 100){
    //zapnutí a vypnutí relé
    digitalWrite(rele1, regBank.get(1));
    digitalWrite(rele2, regBank.get(2));
    digitalWrite(rele3, regBank.get(3));
    digitalWrite(rele4, regBank.get(4));
    digitalWrite(rele5, regBank.get(5));
    digitalWrite(rele6, regBank.get(6));
    digitalWrite(rele7, regBank.get(7));
    digitalWrite(rele8, regBank.get(8));

     
   
    slave.run();
  }
 
  //HCSR-04
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
 
  // Spočítá vzdálenost
  float distance = pulseIn(ECHO, HIGH);
  distance= distance*0.017315f;
  int vzdalenost = (distance * 100) + 0.5;
  if(vzdalenost > 40000) vzdalenost = 40000;
   
  regBank.set(40020, (word) vzdalenost); //vzdálenost od 0 do 1000, 1mm = 1, 1000mm = 1000

  // Spocita teplotu z cidla A0
  int sensorValue = analogRead(A0);
  float volt = (sensorValue/1020.0) * 5.0; //Volts
  float tempC = (volt -0.5) * 10000; //Celcius
  regBank.set(30001, (word) tempC);

    // Spocita teplotu z cidla A1
  int sensorValue1 = analogRead(A1);
  float volt1 = (sensorValue1/1020.0) * 5.0; //Volts
  float tempC1 = (volt1 -0.5) * 10000; //Celcius
  regBank.set(30002, (word) tempC1);
   
  slave.run(); 
}
[url][/url]

Napsal: 23 říj 2016, 21:59
od Cowley
když vysílá, musí být na převodníku DE na HIGH, když přijímá, musí být RE na LOW.
Proto je propoj dohromady a ovládej nějakým Dig. výstupem...

Ale hlavně nikde nevidím zachytávání nějakých přijatých dat na Rx portu nebo alespoň SoftwareSerial Rx portu ?
Leda, že by se o to starala nějaká z knihoven...

Tak to pro začátek nastav "natvrdo" jen na příjem napřímo připojením RE na GND a vyzkoušej to...

Napsal: 23 říj 2016, 22:13
od radekzela
Děkuji za tvůj příspěvek.
Arduino je u mě kámen úrazu. Vůbec ho neumím :-)
Pokud by zde byla dobrá duše která by mě zaslala upravený kod nebo knihovnu s kterým by to fungovalo na TX i na RX s tim automatickým přepínání a zapojením na piny, spadl by mi kámen ze srdce :-)

Opravdu je potřeba jen těch pár relátek a zachování toho ultrazvuku.

Poznámka: S arduinem jsem přišel do kontaktu teprve tento týden :-)

Napsal: 23 říj 2016, 22:26
od Cowley
A že máš v prvním videu MEGA a ve druhém UNO?

Já bych nejprve hardwarově nastavil pouze příjem ze 485 a zkusil bych, zda to šlape. A hlavně to dal na jiné piny než 0 a 1, kde běhá UPLOAD.

Pak by se vidělo.

Taky je možné, že má arduino průběžně odpovídat, že je přítomno, pak hardwarový pevně nastavený příjem nepomůže a nezbyde než rozpitvat knihovnu, kde se komunikace ztrácí...

Napsal: 23 říj 2016, 22:40
od radekzela
To s tím příjmem jsem již zkošel ale HMI musí dostávat odpoveď od arduina aby vůbec zobrazilo ovladací prvky (tlačítka, hodnoty na displeji apod.)
Ty desky mám dvě objednal jsem si obě od číňana společně s těmi převodníky senzory vzdalenosti apod. Ještě mám na cestě ty usb/485 převodníky. S těmi bude možná lepší práce zjistit jak to funkuje. Teď nemám jak dostat 485ku do PC.

Napsal: 23 říj 2016, 22:47
od radekzela
Myslíte že by mohlo fungovat když do kódu přidám jen toto ale nevím jek to dopadne.

Kód: Vybrat vše

#define RS485TxEnablePin 2
#define RS485Baud 9600
#define RS485Format SERIAL_8N1

Napsal: 23 říj 2016, 22:51
od Cowley
A z jakých stránek máš ten odkaz na knihovny?

Napsal: 23 říj 2016, 22:55
od radekzela

Napsal: 23 říj 2016, 23:06
od Cowley
radekzela píše:Myslíte že by mohlo fungovat když do kódu přidám jen toto ale nevím jek to dopadne.

Kód: Vybrat vše

#define RS485TxEnablePin 2
#define RS485Baud 9600
#define RS485Format SERIAL_8N1


Zkus to, ale ještě změň a doplň řádek v programu na
slave.setBaud(&Serial,RS485Baud,RS485Format,RS485TxEnablePin);

Pak by mělo být řízení vyvedeno na PIN 2

A hlavně musíš použít knihovnu v tomto novém odkazu, protože tam je to ovládání zapracované v souboru modbusSlave.cpp
V tom odkaze na začátku vlákna je sice taky tento soubor, ale řízení není podporováno...

Napsal: 23 říj 2016, 23:59
od radekzela
Tak to zabralo už to vypadá že data lezou obousměrně ale je to nějaké zasekané relé mi vybaví až když kliknu třeba 10x na tlačítko na HMI panelu.

Pozoruju na udajich z ultrazvukoveho senzoru že se vždy komunikace rojede rychleji hodnoty vzdalenosti se mění dobře. Natočím video co to dělá.

Napsal: 24 říj 2016, 01:27
od radekzela
Tak zde je to video jak jsem psal. Projevuje se tam nějaké zpoždění :-(
https://www.youtube.com/watch?v=JO98SEikCAc

Ale data chodí ve správném formátu testoval jsem to ještě na teploty a vlhkost na senzou DHT11 a všechna data byla v pořádku.

A ještě jeden poznatek když mám na HMI jen jedno tlačítko na relé bez žádných jiných ovládacích nebo zobrazovacích prvků tak zpoždění je cca 1 sek. .

Zajímavé.

Testováno na tomto kódu:

Kód: Vybrat vše

#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>

//Setup the brewtrollers register bank
//All of the data accumulated will be stored here
modbusDevice regBank;
//Create the modbus slave protocol handler
modbusSlave slave;

#define RS485TxEnablePin 2
#define RS485Baud 19200
#define RS485Format SERIAL_8E1


//deklarování pinů relé karty
int rele1 = 4;
int rele2 = 5;
int rele3 = 6;
int rele4 = 7;
int rele5 = 8;
int rele6 = 9;
int rele7 = 10;
int rele8 = 11;

int ECHO = 12; // Echo pin z HC-SC04 na pinu 2
int TRIG = 13; // Trig pin z HC-SC04 na pin 3

void setup(){   


 
  //Assign the modbus device ID. 
  regBank.setId(1);

  regBank.add(1);
  regBank.add(2);
  regBank.add(3);
  regBank.add(4);
  regBank.add(5);
  regBank.add(6);
  regBank.add(7);
  regBank.add(8);

  regBank.add(30001);   //regist pro teplotni senzor A0
  regBank.add(30002);   //regist pro teplotni senzor A1
  regBank.add(40020);   //registr pro data z ultrazvuku

  slave._device = &regBank; 

  //inicializace sériového portu s rychlostí 9600
  slave.setBaud(&Serial,RS485Baud,RS485Format,RS485TxEnablePin);
 
  pinMode(rele1, OUTPUT);
  pinMode(rele2, OUTPUT);
  pinMode(rele3, OUTPUT);
  pinMode(rele4, OUTPUT);
  pinMode(rele5, OUTPUT);
  pinMode(rele6, OUTPUT);
  pinMode(rele7, OUTPUT);
  pinMode(rele8, OUTPUT);

 
  //Nastaví pin 12 jako vstupní
  pinMode(ECHO, INPUT);
  //Nastaví pin 13 jako výstupní
  pinMode(TRIG, OUTPUT);
}

void loop(){
 
  unsigned long cas = millis();
  while(millis() - cas < 50){
    //zapnutí a vypnutí relé
    digitalWrite(rele1, regBank.get(1));
    digitalWrite(rele2, regBank.get(2));
    digitalWrite(rele3, regBank.get(3));
    digitalWrite(rele4, regBank.get(4));
    digitalWrite(rele5, regBank.get(5));
    digitalWrite(rele6, regBank.get(6));
    digitalWrite(rele7, regBank.get(7));
    digitalWrite(rele8, regBank.get(8));

     
   
    slave.run();
  }
 
  //HCSR-04
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
 
  // Spočítá vzdálenost
  float distance = pulseIn(ECHO, HIGH);
  distance= distance*0.017315f;
  int vzdalenost = (distance * 100) + 0.5;
  if(vzdalenost > 40000) vzdalenost = 40000;
   
  regBank.set(40020, (word) vzdalenost); //vzdálenost od 0 do 1000, 1mm = 1, 1000mm = 1000


   
  slave.run(); 
}

Napsal: 24 říj 2016, 22:04
od radekzela
Tak problém byl vyřešen :-)
Změnilo se zadání adres registrů v HMI panelu a komunikace se ihned rozjela na výbornou.
Původně bylo zadáno pro digitální výstup1 - 0x1 změněno na 0x0001 a ejhle rozjelo se to.

Všem zůčastněným jak na Facebooku tak zde na fóru mockrát děkuji.
A pokusím se to dát nějak smysluplně dohromady kdyby se s tím chtěl taky někdo ještě potrápit.
Teď uvidíme jak se to bude chovat až jich pověsím 20 na linku :-)
Ale to až zítra dnes už stačilo.

Napsal: 25 říj 2016, 05:31
od Cowley
No tak sláva! :)

Napsal: 08 čer 2017, 11:02
od wares
Zdravím mám podobný problé nevedel by mi niekto pomocť z nastavením hmi.

Napsal: 25 črc 2017, 19:02
od radekzela
wares:
Dobrý den právě jsem Vám napsal.
Nahrajte sem fotky jaké máte HMU jak v něm zadáváte hodnoty a jaký požíváte kód.