Arduino Mega Sim900 и 104 протокол
- Войдите на сайт для отправки комментариев
Всем доброго времени суток.
Сразу предупрежу, я новичок в ардуино, поэтому сильно не ругайте за гумнокод и надоедливые вопросы.
Недавно приобрел себе 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 протаколу?
Да что ж это всех новичков итак и тянет на SoftSerial?
Скажите, что Вы в нем нашли? (просто интересно)
На всякий случай: работать может только один SoftSerial, если Вы пытаетесь одновременно использовать более одного, это не будет работать.
Здравствуйте. Я просто плохо знаю С++ поэтому пользовался примерами, про него я вычитал на на этом форуме. Но сегодня после создания темы еще полазил по форуму и нашел что 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); }а можно внятно и подробно, для тупых - обьяснить в чем проблема?
Проблема в том что строчка 068 выводится в монитор порта посимвольно, т.е. сначала буква "H", потом через несколько секунд "e" и т.д. Если что то еще выводить в монитор то получается как на скиншоте.
з.ы. ну и когда вводишь АТ команды, тоже они появляются посимвольно.
Serial1 и Serial2 используют Modbus протокол для общения с компьютером и многофункциональными преобразователями соответственно.
А что вы хотели? У вас невероятная каша в коде, 3 Сериала, 2 RS485 канала - и все это одновременно , извиняюсь. срет в Монитор порта. Конечно все будет перемешиваться.
Уберите отладочный вывод RS485, все эти "Ia addres 2: 166" - и будет выводится нормально.
Вы видать не понимаете о чем я говорю. Даже если я уберу вывод токов и напряжений у меня фраза "Hello, world?" будет выводится секунд 20, символ за символом. Если из кода убрать опрос одного из портов RS485, то Hello world начинает выводится быстрее. Если убрать оба 485-ых, то она появляется сразу вся.
з.ы. имеется ввиду удалить из кода обращение к библиотеке модбас и соответственно сериа1 и сериал2
Вы видать не понимаете о чем я говорю. Даже если я уберу вывод токов и напряжений у меня фраза "Hello, world?" будет выводится секунд 20, символ за символом. Если из кода убрать опрос одного из портов RS485, то Hello world начинает выводится быстрее. Если убрать оба 485-ых, то она появляется сразу вся.
и что в этом удивительного? Вы в код (свой? :) посмотрите - у вас ваша Хелло так и выводится ПОСИМВОЛЬНО между опросами RS485.
И как это можно исправить? Потому что в дальнейшем мне надо будет данные с RS485 передавать в SIM900, а оттуда по 104 протоколу на верхний уровень.
И как это можно исправить?
Собирать свой Хэлловорд сначала в буфере. Потом выводить куда надо.
Не дед, не в том дело. Оно и так в буфере.
E A S T, посмотрите как часто прокручивается loop. например в стр.96 сделать digitalWrite(13, 1);delay(100);digitalWrite(13, 0); в сетапе пин настроить и смотреть на светодиод. SS очень не очень, она будет выводить по символу на обращение к ней, а оно раз (ну почти раз) на loop.
Я уже писал что плохо знаю С++, поэтому не ругаемся на код. сделал так.
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, на команды отвечает, только в конце каждого сообщения какие-то кракозябры выводятся.
Откуда они берутся и как от них избавиться?
я SS уже не использую, переключил GSM на Serial3.
Я уже писал что плохо знаю С++, поэтому не ругаемся на код.
Ок! Базару нихт! Не будем ругаться, будем восхвалять:
--О, какой прекрасный код и как остроумно написан! Как чудесно выводит он в сериал эти великолепные знаки!
Так нормально? Я всё правильно понял?
Вы не правильно поняли. Надо внимательнее читать вопрос, это там где предложение заканчивается "?". Про восхваление ничего не писал. Достаточно ответить на вопрос, а не заниматься восхвалением своих знаний в области программирования ардуино и показывать свое надменное отношение ко всем начинающим в этой области знаний.
Пипец, апять!
Пипец, апять!
Неправильно восхваляем! Мы - "выдающийся", а надо "величайший"! ;)))
Достаточно ответить на вопрос, а не заниматься восхвалением своих знаний в области программирования ардуино и показывать свое надменное отношение ко всем начинающим в этой области знаний.
Я просто для "более лучшего" (так сейчас принято выражаться) понимания уточню. Кому достаточно?
Если про меня, то шобы "да", так "нет"! У меня как-то шире пирамида Маслоу. Ну там еще "хлебоу", "икроу" и все эти вещи... Так что мне - явно недостаточно.И еще окна Овертона нараспашку. ...Да и не мытые опять. Куды бечь?
Пипец, апять!
А можно по существу вопроса?
Судя по описанию функции
Serial.available()
она возвращает количество байт доступных для чтения из последовательного интерфейса связи. Получается в нем что еще есть, но вот откуда это что то еще берется и как его исключить?
Можно и по делу.
1. Все таки нужно, чтобы у тебя заработал ровно и без сбоев стандартный пример подключения модема Sim900. Вот прямо бери пример, как есть, модем на Serial3, консоль на Serial, как обычно. Ничего не меняя в стандартном примере, запусти и напиши о результате.
2. Опрос шины 485 нужно будет проводить в вызовах таймера периодически. Прикинь, как часто твоя система этом нуждается и сколько времени займет весь цикл опроса. Например, если требуется 50миллисек на опрос, то вызывать его желательно не чаще раза в 100-200 мс. Понятно?
3. Давай ты сделаешь шаг 1, а потом я или кто-то из других участников, объяснят тебе, что делать дальше.
4. Самое важное - это НЕ ДИСКУССИОННЫЙ КЛУБ! Если тебе говорят что-то сделать, нужно точно и именно таким способом сделать. После первого косяка - помогать дальше будешь себе сам. Правой рукой. (или левой - пох)
//откуда это что то еще берется и как его исключить?
Берется - с канала связи получено, может мусор. Исключить - читать из Serial пока Serial.available()
не вернет 0.
Про ругаться - еще даже не начинал. Вон люди знают ;)
Пипец, апять!
А можно по существу вопроса?
Судя по описанию функции
Serial.available()
она возвращает количество байт доступных для чтения из последовательного интерфейса связи. Получается в нем что еще есть, но вот откуда это что то еще берется и как его исключить?
Мне сегодня памятник за терпение поставят.
На момент вызова ничего не было, пока читал и обрабатывал еще пришло. "Время - не стоит на месте!"
А можно по существу вопроса?
Я бы с радостью, но не вижу существа в вопросе. Мож, когда увижу, чего и вставлю.
Мне сегодня памятник за терпение поставят.
На воде, с веслом и якорем )))
Мне сегодня памятник за терпение поставят.
скорее, найдут, догонят и подарят итальянский набор для подводного плаванья (верёвку, тазик и цемент)
Можно и по делу.
1. Все таки нужно, чтобы у тебя заработал ровно и без сбоев стандартный пример подключения модема Sim900. Вот прямо бери пример, как есть, модем на Serial3, консоль на Serial, как обычно. Ничего не меняя в стандартном примере, запусти и напиши о результате.
2. Опрос шины 485 нужно будет проводить в вызовах таймера периодически. Прикинь, как часто твоя система этом нуждается и сколько времени займет весь цикл опроса. Например, если требуется 50миллисек на опрос, то вызывать его желательно не чаще раза в 100-200 мс. Понятно?
3. Давай ты сделаешь шаг 1, а потом я или кто-то из других участников, объяснят тебе, что делать дальше.
4. Самое важное - это НЕ ДИСКУССИОННЫЙ КЛУБ! Если тебе говорят что-то сделать, нужно точно и именно таким способом сделать. После первого косяка - помогать дальше будешь себе сам. Правой рукой. (или левой - пох)
Вот за этот ответ спасибо.
Вот, кстати, выше появился Дет Симен. У него есть отличная библиотека таймеров, которая потом поможет тебе правильно организовать опрос твоей шины 485. Попроси у него ссылку.
я думаю, он до неё не дорос еще. Но пусь пропробовает
я думаю, он до неё не дорос еще. Но пусь пропробовает
Дет! А я забыл, у тебя там семафоры есть какие-то, чтобы остановить таймер на время? Тут у поцыэнта же долгий как и опрос шины, так и работа с момедом.. По фэншую семафоры нужны.
там можно остановить и любой таймер и весь список. Потом можно продолжить либо сначала, либо с того места, где остановили. Я часто этим пользуюсь, когда таймауты считаю. Допустим, если из сериала в течение 2 секунд ничего не приходит, я считаю, что передача кончилась, а любой приходящий символ перезапускает таймер сначала. Как только я из сериала всё принял, таймер останавливается до следующего Serial.available() != 0;
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); } }в мониторе получаю следующее
Всё работает? Модем совершает операции? Обрати внимание на скорости каналов. Попробуй поставить скрость работы с компьютером - нормальную, например 115200
и начинай переписывать опрос шины без делей и не в основном цикле, а с помощью дедовых таймеров.
Еще важно убрать глупости с инициализациями в лупе! Сделай два нода и инциализируй их в сетапе.
Да, скорость изменил. Попробую разобраться с таймерами. Так что если пару дне не выйду на связь не теряйте.
Сделай два нода и инциализируй их в сетапе.
Я вспомнил, почему сделал инициализацию в лупе. У меня на одном порту сейчас сидит два слейв устройства, в теории их может быть и больше. Я не смог понять как в него передать сразу несколько адресов устройств при инициализаци.
Два устройства на одном UART?
Коллеги, это к тому, как кидаться "помогать" не видя схемы.
Два устройства на одном UART?
этот UART у меня работает как RS485 по протоколу Modbus. А на него как вы наверно знаете можно подцепить не только одно слейв устройство.
А-а-а, ну тогда Вы неудачно сформулировали. На порту Ардуины у Вас одно устройство (MAX485 или подобное). Я же говорю, без схемы очень трудно - такие недоразумения постоянно вылазят.
Я просто думал что использование библиотеки ModbusMaster подразумевает наличие подключенного устройства на базе микросхемы MAX485 или подобной.
Модбас и 485 ни как не связаны. Это разные уровни абстракции. Железо и софт. Оно конечно бывает, что модбас работает через 485.
Здравствуйте, можете скинуть какой-нибудь пример по работе с вашими таймерами?
Здравствуйте, можете скинуть какой-нибудь пример по работе с вашими таймерами?
вы библиотеку-то открывали? Там обширнейший хелп с примерами
Здравствуйте, можете скинуть какой-нибудь пример по работе с вашими таймерами?
Напишешь потом, кактамчо.