Этап 1. Протокол общения между Arduino Mega и WemosПодключаем по Serial. У Меги их аж 4, я выбрал 1-й.
Rx Меги в Tx Вемоса, соответственно Tx Меги в Rx Вемоса.
Я подключаю напрямую, что есть
неправильно! Поскольку Вемос работает на 3.3вольтах, а Мега на 5-ти, соответственно Вемос может сгореть от 5-ти вольт Меги.
Я это делаю на свой страх и риск, запасной Вемос у меня есть. По науке нужно использовать
преобразователь логических уровней.
Либо Tx от Меги пускать через делитель напряжения, можно использовать переменный резистор (крайнюю ногу на Tx Меги, среднюю на Rx Вемоса, другую крайнюю на землю. Выкрутить так, чтоб между ногой Tx Меги и средней ногой было сопротивление 1/3 от общего сопротивления переменного резистора, т.е. между крайними ногами). Обратный канал преобразовывать необязательно, Мега и 3.3 вольта тоже прекрасно понимает.
Пара слов о протоколе.
Здесь нет совершенно никаких оганичений, данные можно отправлять в любой форме.
Мой выбор:
Принцип работы: master-slave. Вемос у нас будет выступать master, т.е. полностью руководить связью. Периодически он будет отслыть в Вемос запрос на получение данных, Мега при получении этого запроса сразу же их отдает. Кроме того, Вемос может отправлять управляющие команды, при получении которых Мега будет менять свои настройки.
Команды из Вемоса будут идти в таком виде:
Т_12>
"Т" - означает, какой именно параметр мы хотим поменять. "_" - сепаратор. "12" - значение. ">" - символ конца строки.
Информация от Меги будет идти в CSV-формате, т.е. данные разделенные запятыми.
<233, 23.4, 45.6> - примерно так выглядит.
Опять же повторюсь, тут ограничений никаких нет, можно импользовать и только первый вариант для обоих плат, и только второй. Второй вариант больше подходит не для одиночых команд, а для мало-мальски ощутимого массива данных, чуть удобней.
Ближе к делу.
Набросали простейший скетч для Меги, который будет эмулировать получение данных с датчиков (функция Data генерирует случайные показания и заносит их масив data) и один раз в секунду отправлять эти данные в Вемос по Serial1.
float data[10];
long data_last_time;
long transmit_last_time;
//========================================================
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
}
//========================================================
void loop() {
Data(1000);
Transmit(1000);
}
//========================================================
void Data(float freq){
if ((millis()-data_last_time)>freq){
for(int n = 0; n < 10; n++ ){
String m = (String)(random(10000)/100.0);
data[n] = m.toFloat();
}
data_last_time = millis();
}
}
void Transmit(float freq){
if ((millis()-transmit_last_time)>freq){
float summa = 0;
String stroka = "<";
for(int n = 0; n < 10; n++ ){
summa += data[n];
stroka += (String)data[n]+",";
}
stroka += (String)summa + ">";
Serial1.print(stroka);
transmit_last_time = millis();
}
}
Думаю все должно быть понятно, названия переменных говорят сами за себя.
Пара моментов:
1. В данные, кроме собственно них, включается еще контрольная сумма (математическая сумма всех значений строки). В функции Transmit есть цикл в котором происходит одновременно формирование строки из массива данных и подсчитывается их сумма. Затем сумма добавляется в конец строки и передается в Вемос с помощью Serial1.print(stroka);
2. Этот протокол не есть идеальным. Более правильно было бы дробные значения передавать в виде двух байт (по байту на целую и дробную составляющую), я же передаю их как символы, что увеличивает объем переданных данных в 2-3 раза и потребляет ресурсы на преобразования строк в числа и обратно. Для данного скетча это не будет критично, данных мало, поэтому в первую очередь удобство. Для бОльших объемов желательно минимизировать и сделать правильно.
Теперь принимаем данные в Вемосе
float receive_array[20]; //массив с данными, в который будем заносить полученные значения от Меги
String receive_string;
//========================================================
void setup() {
Serial.begin(115200);
}
//========================================================
void loop() {
Receive_from_Mega();
}
//========================================================
void Receive_from_Mega(){
while (Serial.available() > 0) { //если в буфере Serial появилось больше нуля принятых байт
char incomig_char = Serial.read(); //принимает один байт
receive_string += (String)incomig_char; //добавляем его в строку
if ((String)incomig_char == ">") { //если получили символ конца строки
String stroka = receive_string;
receive_string = "";
stroka = stroka.substring(1,stroka.length()-1); //обрезаем символы начала и конца строки
int index = 0; //разбитие строки и занесение в массив. В Ардуино отсутствует такая прекрасная команда как split, поэтому разбивать строку приходится вручную
char separator = ',';
int strIndex[] = { 0, -1 };
int maxIndex = stroka.length() - 1;
for (int i = 0; i <= maxIndex; i++) {
if (stroka.charAt(i) == separator || i == maxIndex) {
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
String value = stroka.substring(strIndex[0], strIndex[1]);
receive_array[index]= value.toFloat(); //заносим в массив полученное значение
index++;
}
}
float summa = 0.0; //проверка контрольной суммы
for (int i = 0; i < 10; i++) {
summa += receive_array
;
}
if(round(receive_array[10]*100) == round(summa*100)){ // здесь важно сравнивать именно округленные значения, поскольку при работе с float нужно помнить, что занося в переменную значение 2.0, там может оказаться 2.0000001, что не даст равенства между ними
Serial.println(" success");
}
}
}
}
To be continued...