Arduino Mega Sim900 и 104 протокол

E A S T
Offline
Зарегистрирован: 16.03.2021

Всем доброго времени суток.

Сразу предупрежу, я новичок в ардуино, поэтому сильно не ругайте за гумнокод и надоедливые вопросы.

Недавно приобрел себе WeMos Mega + WiFi R3 ATmega2560 + ESP8266, SIM900 MINI V4.0 GSM GPRS и MAX485 RS-485 TTL в RS485 MAX485CSA. С++ особо не знаю, поэтому пользовался примерами из IDE.

#include <ModbusMaster.h>//библиотека для ModbusMaster
#include <SoftwareSerial.h>
             
#define MAX485_DE      3
#define MAX485_RE_NEG  2
#define MAX485_DE_1      5
#define MAX485_RE_NEG_1  4

ModbusMaster node;      //объект node класса ModbusMaster
SoftwareSerial mySerial(50, 51); //объект mySerial класса SoftwareSerial

typedef union Convert32
{
    float fFloat;
    int32_t fInt32;
    uint32_t fUInt32;
    int16_t fInt16[2];
    uint16_t fUInt16[2];
} converterU;

typedef union Convert16
{
    int iInteger;
    int16_t iInt16;
    uint16_t iUInt16;
} converterI;

void preTransmission()            //функции для установки состояния контактов DE & RE модуля RS-485
{
  digitalWrite(MAX485_RE_NEG, 1);             
  digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}
void preTransmission1()            //функции для установки состояния контактов DE & RE модуля RS-485
{
  digitalWrite(MAX485_RE_NEG_1, 1);             
  digitalWrite(MAX485_DE_1, 1);
}
void postTransmission1()
{
  digitalWrite(MAX485_RE_NEG_1, 0);
  digitalWrite(MAX485_DE_1, 0);
}
void setup()
{
  
  
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  pinMode(MAX485_RE_NEG_1, OUTPUT);
  pinMode(MAX485_DE_1, OUTPUT);
  
  pinMode(22,INPUT);
  pinMode(23,INPUT);
  
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
  digitalWrite(MAX485_RE_NEG_1, 0);
  digitalWrite(MAX485_DE_1, 0);
  
  mySerial.begin(9600); 
  mySerial.println("Hello, world?");
  
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600); 
  Serial.println("Goodnight moon!");
}

void loop()
{  
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }

  converterI ConverterIa;
  converterI ConverterIb;
  converterU ConverterUa;
  converterU ConverterUb;
  converterU ConverterUc;

  node.begin(2, Serial2);            //Slave ID (адрес ведомого) - 2
  node.preTransmission(preTransmission1);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission1);
  
  node.readInputRegisters(0x10C,1);
  ConverterIa.iUInt16 = node.getResponseBuffer(0x00);

   delay(100);
//   
  node.begin(3, Serial2);            //Slave ID (адрес ведомого) - 3
  node.preTransmission(preTransmission1);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission1);
  
  node.readInputRegisters(0x0044,1);
  ConverterIb.iUInt16 = node.getResponseBuffer(0x00);
  node.readInputRegisters(0x0004,8);
  ConverterUa.fUInt16[0] = node.getResponseBuffer(0x01);
  ConverterUa.fUInt16[1] = node.getResponseBuffer(0x02);
  ConverterUb.fUInt16[0] = node.getResponseBuffer(0x03);
  ConverterUb.fUInt16[1] = node.getResponseBuffer(0x04);
  ConverterUc.fUInt16[0] = node.getResponseBuffer(0x05);
  ConverterUc.fUInt16[1] = node.getResponseBuffer(0x06);

  node.begin(1, Serial1);            //Slave ID (адрес ведомого) - 1
  node.preTransmission(preTransmission);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission);
  node.writeSingleRegister(0x40000,ConverterIa.iInteger);
  node.writeSingleRegister(0x40001,ConverterIb.iInteger);
  node.writeSingleRegister(0x40002,ConverterUa.fFloat);
  node.writeSingleRegister(0x40003,ConverterUb.fFloat);
  node.writeSingleRegister(0x40004,ConverterUc.fFloat);
}

Вроде как все работает, по одному порту опрашивается два устройства, по другому порту эти данные передаются в компьютер. Но текст Hello, world? передается посимвольно с каждым опросом (смотрю через монитор порта). Если оставить как примере softwareserial, все нормально отображается. Когда добавляю еще два порта  для Modbus, начинаются проблемы. 

И еще один вопрос, как можно через GSM модуль передать получаемые данные, по 104 протаколу?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Да что ж это всех новичков итак и тянет на SoftSerial?

Скажите, что Вы в нем нашли? (просто интересно)

На всякий случай: работать может только один SoftSerial, если Вы пытаетесь одновременно использовать более одного, это не будет работать.

E A S T
Offline
Зарегистрирован: 16.03.2021

Здравствуйте. Я просто плохо знаю С++ поэтому пользовался примерами, про него я вычитал на на этом форуме. Но сегодня после создания темы еще полазил по форуму и нашел что SS больше одного не работает да и сама библиотека не очень. Поэтому уже подключил GSM модуль к Serial3, но на результат это не повлияло. Уже и скорости менял, все такой же посимвольный вывод "Hello, world?" 


#include <ModbusMaster.h>//библиотека для ModbusMaster

             
#define MAX485_DE      3
#define MAX485_RE_NEG  2
#define MAX485_DE_1      5
#define MAX485_RE_NEG_1  4

ModbusMaster node;      //объект node класса ModbusMaster

typedef union Convert32
{
    float fFloat;
    int32_t fInt32;
    uint32_t fUInt32;
    int16_t fInt16[2];
    uint16_t fUInt16[2];
} converterU;

typedef union Convert16
{
    int iInteger;
    int16_t iInt16;
    uint16_t iUInt16;
} converterI;

void preTransmission()            //функции для установки состояния контактов DE & RE модуля RS-485
{
  digitalWrite(MAX485_RE_NEG, 1);             
  digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}
void preTransmission1()            //функции для установки состояния контактов DE & RE модуля RS-485
{
  digitalWrite(MAX485_RE_NEG_1, 1);             
  digitalWrite(MAX485_DE_1, 1);
}
void postTransmission1()
{
  digitalWrite(MAX485_RE_NEG_1, 0);
  digitalWrite(MAX485_DE_1, 0);
}
void setup()
{
  
  
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  pinMode(MAX485_RE_NEG_1, OUTPUT);
  pinMode(MAX485_DE_1, OUTPUT);
  
  pinMode(22,INPUT);
  pinMode(23,INPUT);
  
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
  digitalWrite(MAX485_RE_NEG_1, 0);
  digitalWrite(MAX485_DE_1, 0);
  
  Serial.begin(115200);
  Serial1.begin(9600);
  Serial2.begin(9600); 
  Serial3.begin(115200); 
  Serial3.println("Hello, world?");
  Serial.println("Goodnight moon!");
}

void loop()
{  
  if (Serial3.available()) {
    Serial.write(Serial3.read());
  }
  if (Serial.available()) {
    Serial3.write(Serial.read());
  }

 
  
  converterI ConverterIa;
  converterI ConverterIb;
  converterU ConverterUa;
  converterU ConverterUb;
  converterU ConverterUc;

  node.begin(2, Serial2);            //Slave ID (адрес ведомого) - 2
  node.preTransmission(preTransmission1);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission1);
  
  node.readInputRegisters(0x10C,1);
  ConverterIa.iUInt16 = node.getResponseBuffer(0x00);

   delay(100);
//   
  node.begin(3, Serial2);            //Slave ID (адрес ведомого) - 3
  node.preTransmission(preTransmission1);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission1);
  
  node.readInputRegisters(0x0044,1);
  ConverterIb.iUInt16 = node.getResponseBuffer(0x00);
  node.readInputRegisters(0x0004,8);
  ConverterUa.fUInt16[0] = node.getResponseBuffer(0x01);
  ConverterUa.fUInt16[1] = node.getResponseBuffer(0x02);
  ConverterUb.fUInt16[0] = node.getResponseBuffer(0x03);
  ConverterUb.fUInt16[1] = node.getResponseBuffer(0x04);
  ConverterUc.fUInt16[0] = node.getResponseBuffer(0x05);
  ConverterUc.fUInt16[1] = node.getResponseBuffer(0x06);

  node.begin(1, Serial1);            //Slave ID (адрес ведомого) - 1
  node.preTransmission(preTransmission);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission);
  node.writeSingleRegister(0x40000,ConverterIa.iInteger);
  node.writeSingleRegister(0x40001,ConverterIb.iInteger);
  node.writeSingleRegister(0x40002,ConverterUa.fFloat);
  node.writeSingleRegister(0x40003,ConverterUb.fFloat);
  node.writeSingleRegister(0x40004,ConverterUc.fFloat);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

а можно внятно и подробно, для тупых - обьяснить в чем проблема?

E A S T
Offline
Зарегистрирован: 16.03.2021

Проблема в том что строчка 068 выводится в монитор порта посимвольно, т.е. сначала буква "H", потом через несколько секунд "e" и т.д. Если что то еще выводить в монитор то получается как на скиншоте.

з.ы. ну и когда вводишь АТ команды, тоже они появляются посимвольно.

Serial1 и Serial2 используют Modbus протокол для общения с компьютером и многофункциональными преобразователями соответственно.

b707
Offline
Зарегистрирован: 26.05.2017

А что вы хотели? У вас невероятная каша в коде, 3 Сериала, 2 RS485 канала - и все это одновременно , извиняюсь. срет в Монитор порта. Конечно все будет перемешиваться.

Уберите отладочный вывод RS485, все эти "Ia addres 2: 166" - и будет выводится нормально.

E A S T
Offline
Зарегистрирован: 16.03.2021

Вы видать не понимаете о чем я говорю. Даже если я уберу вывод токов и напряжений у меня фраза "Hello, world?" будет выводится секунд 20, символ за символом. Если из кода убрать опрос одного из портов RS485, то Hello world начинает выводится быстрее. Если убрать оба 485-ых, то она появляется сразу вся.

з.ы. имеется ввиду удалить из кода обращение к библиотеке модбас и соответственно сериа1 и сериал2

b707
Offline
Зарегистрирован: 26.05.2017

E A S T пишет:

Вы видать не понимаете о чем я говорю. Даже если я уберу вывод токов и напряжений у меня фраза "Hello, world?" будет выводится секунд 20, символ за символом. Если из кода убрать опрос одного из портов RS485, то Hello world начинает выводится быстрее. Если убрать оба 485-ых, то она появляется сразу вся.

и что в этом удивительного? Вы в код (свой? :) посмотрите - у вас ваша Хелло так и выводится ПОСИМВОЛЬНО между опросами RS485.

E A S T
Offline
Зарегистрирован: 16.03.2021

И как это можно исправить? Потому что в дальнейшем мне надо будет данные с RS485 передавать в SIM900, а оттуда по 104 протоколу на верхний уровень.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

E A S T пишет:

И как это можно исправить?

Собирать свой Хэлловорд сначала в буфере.  Потом выводить куда надо.

Logik
Offline
Зарегистрирован: 05.08.2014

Не дед, не в том дело. Оно и так в буфере.

E A S T, посмотрите как часто прокручивается loop. например в стр.96 сделать digitalWrite(13, 1);delay(100);digitalWrite(13, 0); в сетапе пин настроить и смотреть на светодиод. SS очень не очень, она будет выводить по символу на обращение к ней, а оно раз (ну почти раз) на loop. 

E A S T
Offline
Зарегистрирован: 16.03.2021

Я уже писал что плохо знаю С++, поэтому не ругаемся на код. сделал так.

  int j = Serial3.available();
  char incomingByte[j] = {0};
  int k = Serial.available();
  char outcomingByte[k] = {0};
  

  if (Serial3.available()) {
    for ( int i = 0; i<j; i++) {
    incomingByte[i] = Serial3.read();
    }
    Serial.write(incomingByte);
  }
  if (Serial.available()) {
    for ( int i = 0; i<k; i++) 
      {
        outcomingByte[i] = Serial.read();
      }
    Serial3.write(outcomingByte);
  }

теперь он сразу выводит Hello Word, на команды отвечает, только в конце каждого сообщения какие-то кракозябры выводятся.

Откуда они берутся и как от них избавиться?

E A S T
Offline
Зарегистрирован: 16.03.2021

я SS  уже не использую, переключил GSM на Serial3.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

E A S T пишет:

Я уже писал что плохо знаю С++, поэтому не ругаемся на код.

Ок! Базару нихт! Не будем ругаться, будем восхвалять:

--О, какой прекрасный код и как остроумно написан! Как чудесно выводит он в сериал эти великолепные знаки!

Так нормально? Я всё правильно понял?

E A S T
Offline
Зарегистрирован: 16.03.2021

Вы не правильно поняли. Надо внимательнее читать вопрос, это там где предложение заканчивается "?". Про восхваление ничего не писал. Достаточно ответить на вопрос, а не заниматься восхвалением своих знаний в области программирования ардуино и показывать свое надменное отношение ко всем начинающим в этой области знаний. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Пипец, апять!

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

Пипец, апять!

Неправильно восхваляем! Мы - "выдающийся", а надо "величайший"! ;)))

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

E A S T пишет:

 Достаточно ответить на вопрос, а не заниматься восхвалением своих знаний в области программирования ардуино и показывать свое надменное отношение ко всем начинающим в этой области знаний. 

Я просто для  "более лучшего" (так сейчас принято выражаться) понимания уточню. Кому достаточно?

Если про меня, то шобы "да", так "нет"! У меня как-то шире пирамида Маслоу. Ну там еще "хлебоу", "икроу" и все эти вещи... Так что мне - явно недостаточно.И еще окна Овертона нараспашку. ...Да и не мытые опять. Куды бечь?

E A S T
Offline
Зарегистрирован: 16.03.2021

ЕвгенийП пишет:

Пипец, апять!

А можно по существу вопроса? 

Судя по описанию функции 

Serial.available()

она возвращает количество байт доступных для чтения из последовательного интерфейса связи. Получается в нем что еще есть, но вот откуда это что то еще берется и как его исключить? 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Можно и по делу.

1. Все таки нужно, чтобы у тебя заработал ровно и без сбоев стандартный пример подключения модема Sim900. Вот прямо бери пример, как есть, модем на Serial3, консоль на Serial, как обычно. Ничего не меняя в стандартном примере, запусти и напиши о результате.

2. Опрос шины 485 нужно будет проводить в вызовах таймера периодически. Прикинь, как часто твоя система этом нуждается и сколько времени займет весь цикл опроса. Например, если требуется 50миллисек на опрос, то вызывать его желательно не чаще раза в 100-200 мс. Понятно?

3. Давай ты сделаешь шаг 1, а потом я или кто-то из других участников, объяснят тебе, что делать дальше.

4. Самое важное - это НЕ ДИСКУССИОННЫЙ КЛУБ! Если тебе говорят что-то сделать, нужно точно и именно таким способом сделать. После первого косяка - помогать дальше будешь себе сам. Правой рукой. (или левой - пох)

Logik
Offline
Зарегистрирован: 05.08.2014

//откуда это что то еще берется и как его исключить? 

Берется - с канала связи получено, может мусор. Исключить - читать из Serial пока Serial.available()

не вернет 0.

Про ругаться - еще даже не начинал. Вон люди знают ;)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

E A S T пишет:

ЕвгенийП пишет:

Пипец, апять!

А можно по существу вопроса? 

Судя по описанию функции 

Serial.available()

она возвращает количество байт доступных для чтения из последовательного интерфейса связи. Получается в нем что еще есть, но вот откуда это что то еще берется и как его исключить? 

Мне сегодня памятник за терпение поставят.

На момент вызова ничего не было, пока читал и обрабатывал еще пришло. "Время - не стоит на месте!"

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

E A S T пишет:

А можно по существу вопроса? 

Я бы с радостью, но не вижу существа в вопросе. Мож, когда увижу, чего и вставлю.

Logik
Offline
Зарегистрирован: 05.08.2014

wdrakula пишет:

Мне сегодня памятник за терпение поставят.

На воде, с веслом и якорем )))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

wdrakula пишет:

Мне сегодня памятник за терпение поставят.

скорее, найдут, догонят и подарят итальянский набор для подводного плаванья (верёвку, тазик и цемент)

E A S T
Offline
Зарегистрирован: 16.03.2021

wdrakula пишет:

Можно и по делу.

1. Все таки нужно, чтобы у тебя заработал ровно и без сбоев стандартный пример подключения модема Sim900. Вот прямо бери пример, как есть, модем на Serial3, консоль на Serial, как обычно. Ничего не меняя в стандартном примере, запусти и напиши о результате.

2. Опрос шины 485 нужно будет проводить в вызовах таймера периодически. Прикинь, как часто твоя система этом нуждается и сколько времени займет весь цикл опроса. Например, если требуется 50миллисек на опрос, то вызывать его желательно не чаще раза в 100-200 мс. Понятно?

3. Давай ты сделаешь шаг 1, а потом я или кто-то из других участников, объяснят тебе, что делать дальше.

4. Самое важное - это НЕ ДИСКУССИОННЫЙ КЛУБ! Если тебе говорят что-то сделать, нужно точно и именно таким способом сделать. После первого косяка - помогать дальше будешь себе сам. Правой рукой. (или левой - пох)

Вот за этот ответ спасибо.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Вот, кстати, выше появился Дет Симен. У него есть отличная библиотека таймеров, которая потом поможет тебе правильно организовать опрос твоей шины 485. Попроси у него ссылку.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

я думаю, он до неё не дорос еще. Но пусь пропробовает

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

DetSimen пишет:

я думаю, он до неё не дорос еще. Но пусь пропробовает

Дет! А я забыл, у тебя там семафоры есть какие-то, чтобы остановить таймер на время? Тут у поцыэнта же долгий как и опрос шины, так и работа с момедом.. По фэншую семафоры нужны.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

там можно остановить и любой таймер и весь список. Потом можно продолжить либо сначала, либо с того места, где остановили.  Я часто этим пользуюсь, когда таймауты считаю.  Допустим, если из сериала в течение 2 секунд ничего не приходит, я считаю, что передача кончилась, а любой приходящий символ перезапускает таймер сначала. Как только я из сериала всё принял, таймер останавливается до следующего Serial.available() != 0;

E A S T
Offline
Зарегистрирован: 16.03.2021

wdrakula пишет:

1. Все таки нужно, чтобы у тебя заработал ровно и без сбоев стандартный пример подключения модема Sim900. Вот прямо бери пример, как есть, модем на Serial3, консоль на Serial, как обычно. Ничего не меняя в стандартном примере, запусти и напиши о результате.

В стандартных примерах я нашел только MultiSerial, он больше подходит

вот его код

void setup() {
  // initialize both serial ports:
  Serial.begin(9600);
  Serial3.begin(9600);
}

void loop() {
  // read from port 1, send to port 0:
  if (Serial3.available()) {
    int inByte = Serial3.read();
    Serial.write(inByte);
  }

  // read from port 0, send to port 1:
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial3.write(inByte);
  }
}

в мониторе получаю следующее 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Всё работает? Модем совершает операции? Обрати внимание на скорости каналов. Попробуй поставить скрость работы с компьютером - нормальную, например 115200

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

и начинай переписывать опрос шины без делей и не в основном цикле, а с помощью дедовых таймеров.

Еще важно убрать глупости с инициализациями в лупе! Сделай два нода и инциализируй их в сетапе.

E A S T
Offline
Зарегистрирован: 16.03.2021

Да, скорость изменил. Попробую разобраться с таймерами. Так что если пару дне не выйду на связь не теряйте.

E A S T
Offline
Зарегистрирован: 16.03.2021

wdrakula пишет:

Сделай два нода и инциализируй их в сетапе.

Я вспомнил, почему сделал инициализацию в лупе. У меня на одном порту сейчас сидит два слейв устройства, в теории их может быть и больше. Я не смог понять как в него передать сразу несколько адресов устройств при инициализаци.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

E A S T пишет:
У меня на одном порту сейчас сидит два слейв устройства

Два устройства на одном UART?

Коллеги, это к тому, как кидаться "помогать" не видя схемы.

E A S T
Offline
Зарегистрирован: 16.03.2021

ЕвгенийП пишет:

Два устройства на одном UART?

этот UART у меня работает как RS485 по протоколу Modbus. А на него как вы наверно знаете можно подцепить не только одно слейв устройство.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А-а-а, ну тогда Вы неудачно сформулировали. На порту Ардуины у Вас одно устройство (MAX485 или подобное). Я же говорю, без схемы очень трудно - такие недоразумения постоянно вылазят.

E A S T
Offline
Зарегистрирован: 16.03.2021

Я просто думал что использование библиотеки ModbusMaster подразумевает наличие подключенного устройства на базе микросхемы MAX485 или подобной.

nik182
Offline
Зарегистрирован: 04.05.2015

Модбас и 485 ни как не связаны. Это разные уровни абстракции. Железо и софт. Оно конечно бывает, что модбас работает через 485.

E A S T
Offline
Зарегистрирован: 16.03.2021

Здравствуйте, можете скинуть какой-нибудь пример по работе с вашими таймерами?

b707
Offline
Зарегистрирован: 26.05.2017

E A S T пишет:

Здравствуйте, можете скинуть какой-нибудь пример по работе с вашими таймерами?

вы библиотеку-то открывали? Там обширнейший хелп с примерами

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

E A S T пишет:

Здравствуйте, можете скинуть какой-нибудь пример по работе с вашими таймерами?

Напишешь потом, кактамчо.