GSM(SIM900) + SD

ustas
Offline
Зарегистрирован: 12.03.2012

Два дня бьюсь с какой-то странной ситуацией.

Есть плата GBoard: http://iteadstudio.com/store/images/produce/Platform/ArduinoCom/GBoard/GBoard_DS.pdf

На борту GSM-модуль (SIM900), SD карта и интерфейс для nRF24L01+ (аппаратный SPI, CS=10 и CS=9 соответственно).

Для работы с GSM-Модулем используется библиотека: http://code.google.com/p/gsm-shield-arduino/downloads/list (версия 3.09)

Для работы с SD используется библиотека SDFat (где взял, уже не помню) или библиотека SD (аналогично не помню, отуда взял).

Примеры работают без проблем - все четко (в Serial превосходно отдают отладочные сообщения и т.п.). Но только, если работают по отдельности...

Как только начинаю объединять два примера в один скетч - все, "приехали". В ком-порт практически ничего не появляется (изредка приходят отладочные сообщения от GSM-модуля, но крайне редко).

Простенький скетч для примера:

// GSM
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"

// SD
#include <SPI.h>
#include <SD.h>
const uint8_t SDchipSelect = 10;

SMSGSM sms;

Sd2Card card;

boolean gsmstarted=false; // флаг того, что GSM стартовал

void setup() 
{
  Serial.begin(9600);
  Serial.println("GSM-SD testing.");
  
  // включим GSM
  pinMode(6, OUTPUT); 
  digitalWrite(6, HIGH);
  
  if (gsm.begin(9600)){
    Serial.println("\nstatus=READY");
    gsmstarted=true;  
  }
  else Serial.println("\nstatus=IDLE");
  
  if(gsmstarted){
    Serial.println("GSM OK");
  }
  
  if (!SD.begin(SDchipSelect)) {
    Serial.println("Card failed, or not present");
  }
  else
    Serial.println("Card initialized.");
}

void loop() {}

в ком-порт не приходит даже строка "GSM-SD testing."

В чем "грабли"? Куда копать?

maksim
Offline
Зарегистрирован: 12.02.2012

А перемычки UART Setting как установлены? Как я помню если использовать библу <SoftwareSerial.h> то нужно указать ноги RX и TX...

ustas
Offline
Зарегистрирован: 12.03.2012

 Перемычки стоят как во второй картинке в даташите:

ST – D2(Software Rx/Tx of Arduino)
SR – D3(Software Rx/Tx of Arduino)

И стоят они, похоже, правильно (ведь по отдельности примеры из библиотек работают без проблем). Удивительно то, что когда примеры объединяются - в последовательный порт толком ничего не отдается.

ustas
Offline
Зарегистрирован: 12.03.2012

 Есть какие-нибудь мысли, которые бы прояснили ситуацию с выводом данных в последовательный порт? Почему по отдельности скетчи работают (и выдают отладочную информацию), а вот вместе "партизанят" и ничего не отдают?

Хотя бы в какую сторону копать? 

Если из скетча, что привел выше выбросить или SD или GSM часть - все работает нормально... 

P.S. библиотеку SDFat брал отсюда: http://code.google.com/p/sdfatlib/

axill
Offline
Зарегистрирован: 05.09.2011

Интересная тема, подключусь. Жду такую же плату и мне наверно будет сложнее, хочу и XBee использовать и GSM и nRF24L01

На какие пины джамперами подключен UART GSM модуля? На 0-1 или на 2-3? Мне видится, что есть конфликт двух UART

ustas
Offline
Зарегистрирован: 12.03.2012

ustas пишет:

 Перемычки стоят как во второй картинке в даташите:

ST – D2(Software Rx/Tx of Arduino)
SR – D3(Software Rx/Tx of Arduino)

Вопрос, почему они не конфликтуют по отдельности, но абсолютно не работоспособны вместе?

P.S. библиотеку для nRF24L01+ не подключаю, пока не разберусь с работой GSM и SD... как разберусь, и беспроводной модуль будет задействован.

axill
Offline
Зарегистрирован: 05.09.2011

ustas пишет:

ustas пишет:

 Перемычки стоят как во второй картинке в даташите:

ST – D2(Software Rx/Tx of Arduino)
SR – D3(Software Rx/Tx of Arduino)

Вопрос, почему они не конфликтуют по отдельности, но абсолютно не работоспособны вместе?

P.S. библиотеку для nRF24L01+ не подключаю, пока не разберусь с работой GSM и SD... как разберусь, и беспроводной модуль будет задействован.

Если GSM подключен к софтверному UART то зачем использовать SoftwareSerial?

Замени SoftwareSerial на Serial и проверь. По идее в библиотеке GSM должна быть возможность выбора пинов через которые работать. Если не заработает - переключи GSM на D0/D1 и верни обратно SoftwareSerial только его нужно явно инициализировать на пины 2 и 3

maksim
Offline
Зарегистрирован: 12.02.2012

Вы как то проигнарировали эту фразу

maksim пишет:

Как я помню если использовать библу <SoftwareSerial.h> то нужно указать ноги RX и TX...

#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);

 

// GSM
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"

// SD
#include <SPI.h>
#include <SD.h>
const uint8_t SDchipSelect = 10;

SoftwareSerial Serial1(2, 3);

SMSGSM sms;

Sd2Card card;

boolean gsmstarted=false; // флаг того, что GSM стартовал

void setup() 
{
  Serial.begin(9600);
  Serial.println("GSM-SD testing.");
  
  // включим GSM
  pinMode(6, OUTPUT); 
  digitalWrite(6, HIGH);
  
  if (gsm.begin(9600)){
    Serial.println("\nstatus=READY");
    gsmstarted=true;  
  }
  else Serial.println("\nstatus=IDLE");
  
  if(gsmstarted){
    Serial.println("GSM OK");
  }
  
  if (!SD.begin(SDchipSelect)) {
    Serial.println("Card failed, or not present");
  }
  else
    Serial.println("Card initialized.");
}

void loop() {}

 

axill
Offline
Зарегистрирован: 05.09.2011

maksim пишет:

Вы как то проигнарировали эту фразу

maksim пишет:

Как я помню если использовать библу <SoftwareSerial.h> то нужно указать ноги RX и TX...

#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);

пина 2 и 3 сейчас у ТС заведены на GSM

maksim
Offline
Зарегистрирован: 12.02.2012

ustas пишет:

 Перемычки стоят как во второй картинке в даташите:

ST – D2(Software Rx/Tx of Arduino)
SR – D3(Software Rx/Tx of Arduino)
 

ustas
Offline
Зарегистрирован: 12.03.2012

оппа... завелось!

Проблема оказалась "железячной". 

Если смотреть даташит на плату - то на картинке, где выбираются пины, используются два блока джамперов (два джампера на левом блоке и два - на правом). Производитель почему-то укомплектовал плату всего двумя джамперами (для левого блока), а правый блок был без джамперов... 

Как только добавил еще два джампера и полностью воспроизвел картинку - все заработало сразу! Обе библиотеки работают совместно.

 

P.S. в файле GSM.cpp прописаны пины для GSM-модуля:

#define _GSM_TXPIN_ 2
#define _GSM_RXPIN_ 3

 

maksim
Offline
Зарегистрирован: 12.02.2012

axill пишет:

maksim пишет:

Вы как то проигнарировали эту фразу

maksim пишет:

Как я помню если использовать библу <SoftwareSerial.h> то нужно указать ноги RX и TX...

#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);

пина 2 и 3 сейчас у ТС заведены на GSM

Библиотеке SoftwareSerial в любом случае надо знать на каких выводах поднимать UART. Но действительно надо перемычки тогда по другому ставить, что бы GSM оказался на 0 и 1 выводах.

ustas
Offline
Зарегистрирован: 12.03.2012

Нда... рано обрадовался.

Похоже, ошибка еще интереснее. Тестовый пример из первого поста - завелся. Но вот если добавить всего одну строчку (просто отправить СМС) - все, "приехали". 

sms.SendSMS("+79641234567", "Start Ok");

Опять никакой отладочной информации. Если строчку с отправкой СМС закомментировать - опять работает. 

Теперь-то на что грешить?

Посмотрел размеры скетчей - разница в (14504 байта и 15602 байта соответственно). Вроде как на недостаток памяти еще рано жаловаться (напомню, используется 328 камушек).

P.S. пины для SoftwareSerial указывал - разницы в поведении скетчей нет.

leshak
Offline
Зарегистрирован: 29.09.2011

 А питаетесь от USB? Уже несколько раз сталкивался что шилды всяких приемников/передатчиков начинают глючить пока не возьмешь внешний блок питания. Причем именно "плавают" проблемами. Вроде работают, а вроде и нет.

И еще, у SoftwareSerial http://arduino.cc/hu/Reference/SoftwareSerial есть ограничение на каких пинах можно RX использовать. Правда там упоминается что "не на всех" можно на меге и на Leonardo... так что скорее, скорее всего, "дело не в этом", но... может еще и это стоит проверить.

ustas
Offline
Зарегистрирован: 12.03.2012

Без нормального внешнего внешнего питания GSM-модуль вообще включаться отказывался. Так что причина не в этом...

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

Максимум, чего пока удалось:

- примеры с GSM (звонки, смс);

- примеры с SD (чтение, запись и т.п.)

- подцепить RTC и отправлять смс (где есть дата-время);

- заставить работать беспроводной модуль и отправлять ему команды через СМС

Но вот как только пытаюсь объединить все функции - все, "приехали". Все компилируется, скетчи по объемам вроде как совершенно нормальные... 

maksim
Offline
Зарегистрирован: 12.02.2012

Я бы на вашем месте для начала подключил GSM модуль к аппаратному UART (к D0 и D1), а програмный использовал бы для вывода в сериал монитор.

ustas
Offline
Зарегистрирован: 12.03.2012

 Интересно, может, все-таки проблема в размере скетча? 

Может ли быть так, что у 328 камня почему-то только "половина памяти"??? 

maksim
Offline
Зарегистрирован: 12.02.2012

Какой памяти?

ustas
Offline
Зарегистрирован: 12.03.2012

maksim пишет:

Я бы на вашем месте для начала подключил GSM модуль к аппаратному UART (к D0 и D1), а програмный использовал бы для вывода в сериал монитор.

Попробвал. Переставил джампера, в файле GSM.cpp поправил номера пинов. 

Не работают даже примеры:

ERROR: SIM900 doesn't answer. Check power and serial pins in GSM.cpp

 

maksim
Offline
Зарегистрирован: 12.02.2012

Если не работает с аппаратным UART, значит что то не так делаете.

ustas
Offline
Зарегистрирован: 12.03.2012

maksim пишет:

Какой памяти?

флеш-памяти.. той, которой должно быть 32к

maksim
Offline
Зарегистрирован: 12.02.2012

А что у вас скейтчи получаются по 16 кБ ???

ustas
Offline
Зарегистрирован: 12.03.2012

 дык, догадываюсь.. но не понимаю, как сделать правильно и как проверить?

Можете подсказать какой-нибудь простой примерчик, который помог-бы проверить?

maksim
Offline
Зарегистрирован: 12.02.2012

Вы вот этот пример проверяли? 

// GSM
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"

// SD
#include <SPI.h>
#include <SD.h>
const uint8_t SDchipSelect = 10;

SoftwareSerial Serial1(2, 3);

SMSGSM sms;

Sd2Card card;

boolean gsmstarted=false; // флаг того, что GSM стартовал

void setup() 
{
  Serial.begin(9600);
  Serial.println("GSM-SD testing.");
  
  // включим GSM
  pinMode(6, OUTPUT); 
  digitalWrite(6, HIGH);
  
  if (gsm.begin(9600)){
    Serial.println("\nstatus=READY");
    gsmstarted=true;  
  }
  else Serial.println("\nstatus=IDLE");
  
  if(gsmstarted){
    Serial.println("GSM OK");
  }
  
  if (!SD.begin(SDchipSelect)) {
    Serial.println("Card failed, or not present");
  }
  else
    Serial.println("Card initialized.");
}

void loop() {}

Как перемычки ставили?

leshak
Offline
Зарегистрирован: 29.09.2011

ustas пишет:

maksim пишет:

Какой памяти?

флеш-памяти.. той, которой должно быть 32к

Так "флеш" это аналог "винчестера" у компа,а есть еще оперативка. И у 328-го камня, ее, если не изменяет память, всего 2k

И "сколько ее осталось" не всегда можно сказать точно.

Вот пара ссылок на эту тему

ustas
Offline
Зарегистрирован: 12.03.2012

maksim пишет:

А что у вас скейтчи получаются по 16 кБ ???

угу... :( .. если размер скетча 14к - еще работает, а вот если больше 15к - уже "грабли"

maksim
Offline
Зарегистрирован: 12.02.2012

Для начала настройте програмный UART и попробуйте вот этот пример

#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);

void setup() {
  Serial1.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  Serial1.println(sensorValue, DEC);
}

Что в сериал мониторе?

ustas
Offline
Зарегистрирован: 12.03.2012

maksim пишет:

Вы вот этот пример проверяли? 

Да, проверял. Работает, если перемычки стоят как во втором изображении в даташите (Software UART to SIM900, Hardware UART to Specific)

ustas
Offline
Зарегистрирован: 12.03.2012

maksim пишет:

Для начала настройте програмный UART и попробуйте вот этот пример

#include <SoftwareSerial.h>
SoftwareSerial Serial1(2, 3);

void setup() {
  Serial1.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  Serial1.println(sensorValue, DEC);
}

Что в сериал мониторе?

полная тишина при любом положении перемычек

maksim
Offline
Зарегистрирован: 12.02.2012

А что значит при любом положении?

maksim
Offline
Зарегистрирован: 12.02.2012

Ну тогда вот так попробуйте

#include <SoftwareSerial.h>
SoftwareSerial Serial1(3, 2);

void setup() {
  Serial1.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  Serial1.println(sensorValue, DEC);
}

 

ustas
Offline
Зарегистрирован: 12.03.2012

Как в варианте "Hardware UART to SIM900, Software UART to Specific", так и в варианте "Software UART to SIM900, Hardware UART to Specific"

Напомню, речь идет о плате GBoard: http://iteadstudio.com/store/images/produce/Platform/ArduinoCom/GBoard/G...

К компу плата подключается через программатор http://iteadstudio.com/store/images/produce/Shield/Focav2.1/foca.pdf

ustas
Offline
Зарегистрирован: 12.03.2012

maksim пишет:

Ну тогда вот так попробуйте

#include <SoftwareSerial.h>
SoftwareSerial Serial1(3, 2);

void setup() {
  Serial1.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  Serial1.println(sensorValue, DEC);
}

 

опять тишина

ustas
Offline
Зарегистрирован: 12.03.2012

leshak пишет:

ustas пишет:

maksim пишет:

Какой памяти?

флеш-памяти.. той, которой должно быть 32к

Так "флеш" это аналог "винчестера" у компа,а есть еще оперативка. И у 328-го камня, ее, если не изменяет память, всего 2k

И "сколько ее осталось" не всегда можно сказать точно.

Вот пара ссылок на эту тему

и про это тоже думал уже, попробую посмотреть, какие "объемы" свободны...

maksim
Offline
Зарегистрирован: 12.02.2012

У вас что то с библиотекой SoftwareSerial, попробуйте другую скачать, помоему есть какая то новая библа, что то типа NewSoftwareSerial.

 

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

У вас что то с библиотекой SoftwareSerial, попробуйте другую скачать, помоему есть какая то новая библа, что то типа NewSoftwareSerial.

 

Вопреки названию NewSoftwareSerial это как раз "старая библиотека". Она переименовалась в SoftwareSerial и вошла в стандартную поставку ArduinoIDE начиная с версии 1.0

ustas
Offline
Зарегистрирован: 12.03.2012

ustas пишет:

и про это тоже думал уже, попробую посмотреть, какие "объемы" свободны...

миленько...

воспользовался функцией:

int availableMemory() {
  int size = 2048; // Use 2048 with ATmega328
  byte *buf;

  while ((buf = (byte *) malloc(--size)) == NULL)
    ;

  free(buf);

  return size;
}

Вывел результаты этой функции последней строчкой в фукнции setup() из первого поста. 

Результат впечатляет - 143 (сто сорок три). 

провел эксперимент. 

Простой скетч:

void setup()
{
  Serial.begin(9600);
  Serial.println(availableMemory());
}

void loop(){}

размер скетча - 2954 байта, в результатах вывода - 1795

Теперь чуть усложним:

#include "SIM900.h"
#include <SoftwareSerial.h>

void setup()
{
  Serial.begin(9600);
  Serial.println(availableMemory());
}

void loop(){}

Размер скетча - 9196 байт и в результатах вывода уже скромные 856

 

Похоже, надо или искать другие библиотеки или писать самому...

axill
Offline
Зарегистрирован: 05.09.2011

А как прошивку делаете плате? У меня такая же, взял преходник для ардуины, которым я arduino mini pro шью, подключил пины 3.3в, GND, RX, TX, DTR. В Arduino IDE выбрал arduino Uno - пишут ошибку при прошивке. Пробовал прямо подключать (rx->rx, tx->tx)  и перекресно (rx->tx, tx->rx). ошибка одинаковая

Опишите как вы прошиваете и какой у вас переходник usb<->uart, какую плату выбираете в Arduino IDE?

tERBO
Offline
Зарегистрирован: 11.12.2012

Надо выбирать arduino duemilanove - у UNO загрузчик другой.

Я шью обычным кабелем USB-COM на чипе Prolific. Пдключаю RX, TX, Землю, ресет жму ручками - всё работает.

Вопрос ко всем - у кого есть какие наработки по этой плате? Залил демо-скетч из стандартной библиотеки - звонок принимает, через 5 секунд даёт отбой, всё ок. Добавляю строчку gsm.SendDTMFSignal(5); после поднятия трубки, звоню, слушаю - в трубке тишина...

ustas
Offline
Зарегистрирован: 12.03.2012

Завел на этой плате RF-модуль и с помощью СМС-команд опрашиваю другие модули (эта плата коммуницирует с ними, получет ответ - значение параметров и пуляет ответную СМС с полученным значением). Аналогично работает и управление ведомыми модулями (отправка конкретному модулю конкретную команду - в ответ "ок" или "wrong", если что-то не получилось).

Со звонками пока не заморачивался, еще надо то, что описал выше до нормального вида довести.

axill
Offline
Зарегистрирован: 05.09.2011

ustas пишет:

Завел на этой плате RF-модуль и с помощью СМС-команд опрашиваю другие модули (эта плата коммуницирует с ними, получет ответ - значение параметров и пуляет ответную СМС с полученным значением). Аналогично работает и управление ведомыми модулями (отправка конкретному модулю конкретную команду - в ответ "ок" или "wrong", если что-то не получилось).

Со звонками пока не заморачивался, еще надо то, что описал выше до нормального вида довести.

поделитесь кодом

Borland
Offline
Зарегистрирован: 17.05.2012

Сталкивался с такой проблемой с Icomsat 1.1 от Iteadstudio

псоле подключения питания модуль не хотел запускаться

Serial.println("ERROR: SIM900 doesn't answer. Check power and serial pins in GSM.cpp");

сделал как советуют програмный резет

again:  
 #ifdef BUTTONS
 
 #endif
  Serial.println("system startup"); 
  
   if (gsm.begin(9600))
    Serial.println("\nstatus=READY");
  else {Serial.println("\nstatus=IDLE");
    pinMode(9, OUTPUT); 
    pinMode(10, OUTPUT); 
    digitalWrite(9, HIGH);   // sets the LED on
    delay(600);                  // waits for a second
    digitalWrite(9, LOW);
     goto again; 

 надежно зависал

поставил дебаг принтов как в библиотеке, так и в HardwareSerial помойму, у меня Мега

 

выяснилось что на скорости 115000 контроллер вис на Serial.flush , в причинах не разобрался, просто выкинул последний цикл из GSM::begin() инициализации на разной скорости.

GSM модуль стал надежно подыматься

Что касается библиотеки, то она очень избыточна, стараюсь обходится функциями  GSM::SendATCmdWaitResp

либо просто анализирую сериал на входе GSM

 

Не очень ясно зачем RTC цеплять, в GSM модуле часы есть с поддержкой от оператора сети.

 

tERBO
Offline
Зарегистрирован: 11.12.2012

Не могу понять в чём дело - плата вдруг перестала видеть GSM модуль (у меня gboard). Включил Debug - смотрю инициализация проходит без замечаний, а когда доходит до рабочего цикла то постоянно пишет "no response".

Хотел подключится к GSM модулю напрямую, но как бы я не переставлял перемычки у меня всё время на выходе последовательный порт "ардуины". Даже вобще без перемычек я вижу сообщения от микроконтроллера. То ли я неправильно понял назначение этих перемычек то ли у меня плата кривая попалась? В общем помогите отловить багу, а то я уже не знаю что с ней делать :(

ustas
Offline
Зарегистрирован: 12.03.2012

axill пишет:

поделитесь кодом

Код кривой, но работает.

Основные куски работающего кода взяты из темы: http://arduino.ru/forum/proekty/peredacha-temperatury-s-datchikov-dht11-ds18b20-cherez-nrf24l01

Выкладваю "как есть" без каких либо гарантий :)

Для того, чтобы получить значение конкретного датчика определенного модуля - отправляем СМС вида:

0 TEST 0

0 - получить значение

TEST - название модуля

0 - номер датчика.

Код блока GSM (плата GBoard):

#include "SIM900.h"
#include <SoftwareSerial.h>
//If not used, is better to exclude the HTTP library,
//for RAM saving.
//If your sketch reboots itself proprably you have finished,
//your memory available.
//#include "inetGSM.h"
#include <SPI.h>
#include <Mirf.h>
#include <ASLibrary1.h>
#include <MirfHardwareSpiDriver.h>

/*
GetAnswer(addr, 1, 0); - сколько датчиков
 GetAnswer(addr, 2, 0); - произвести измерение
 GetAnswer(addr, 4, 1); - вернуть значение датчика 1 (счет начинается с 0)
 GetAnswer(addr, 5, 2); - выполнить команду 2 (счет начинается с 0)
 */

//If you want to use the Arduino functions to manage SMS, uncomment the lines below.
#include "sms.h"
SMSGSM sms;

//To change pins for Software Serial, use the two lines in GSM.cpp.

//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.

//Simple sketch to send and receive SMS.

int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
char position;
char unitID[5];  //идентификатор блока
int command; //команда (0 - Get, 1 - Set)
unsigned int attr;        //аттрибут (команда или номер датчика)
char buf[9];
unsigned int params;

void setup() 
{
  pinMode(6, OUTPUT); 
  digitalWrite(6, HIGH);
  //delay(10000);
  //Serial connection.
  
  //Serial.begin(9600);
  //Serial.println("GSM Shield testing.");

  //Start configuration of shield with baudrate.
  //For http uses is raccomanded to use 4800 or slower.
  if (gsm.begin(2400)){
    //Serial.println("\nstatus=READY");
    started=true;  
  }
  else {
    //Serial.println("\nstatus=IDLE");
  }

  if(started){
    //Enable this two lines if you want to send an SMS.
    sms.SendSMS("+79641234567", "Starting OK!");
  }
  // Зачистим сим-карту от старых СМС
  for(position=0;position<=21;position++) sms.DeleteSMS(position);

};

void loop() 
{
  position = sms.IsSMSPresent(SMS_UNREAD);
  if(position){
    if(sms.GetSMS(position, n, smsbuffer, 160))
    {
      //Serial.println(n);
      //Serial.println(smsbuffer);
      // разбираем строку на команды
      params = sscanf(smsbuffer, "%d%s%d", &command, &unitID, &attr);
      if (params >= 2) { // если получили больше 2 параметров - обрабатываем
        //Serial.print("Command=");
        //Serial.println(command);
        //Serial.print("unitID=");
        //Serial.println(unitID);
        //Serial.print("data=");
        //Serial.println(attr);
        
        SetModule(unitID);
        
        if (command==0 && params==3){
          AS_Answer MyAnswer=GetAnswer(unitID, 2, 0);
          if (MyAnswer.Status == 1) {
            MyAnswer=GetAnswer(unitID, 4, attr);
            if(MyAnswer.Status == 1) {
              dtostrf(MyAnswer.Value,8,1,buf);
              sms.SendSMS(n, buf);
            }
          }
          else {
            sms.SendSMS(n, "Wrong measure!");
          }
        }
        if (command==1 && params==3){
          AS_Answer MyAnswer=GetAnswer(unitID, 5, attr);
          if(MyAnswer.Status == 1){
            sms.SendSMS(n, "Ok!");
          }
          else {
            sms.SendSMS(n, "Wrong!");
          }
        }
      } 
      else {    
        // иначе просто перешлем сообщение
        sms.SendSMS("+79641234567", n);
        sms.SendSMS("+79641234567", smsbuffer);
      }
      sms.DeleteSMS(position);  // после завершения обработки - удаляем сообщение
    }
  }
};

// устанавливаем адрес модуля, с которым работаем
void SetModule(char *addr){
  Mirf.spi = &MirfHardwareSpi;

  Mirf.csnPin = 9;
  Mirf.cePin = 8;
  Mirf.init();

  Mirf.setRADDR((byte *)"GSM1");// Устанавливаем адрес, под которым будем принимать данные
  Mirf.setTADDR((byte *)addr); //Устанавливаем адрес, окуда считываем данные

  Mirf.payload = AS_NRF24L01_payload;
  Mirf.channel = AS_NRF24L01_channel; //Задаем канал
  Mirf.config(); 

  //myDelay(1000);
}

//Посылает команду на устройство и вовращает ответ
AS_Answer GetAnswer(char *addr, byte Command, byte Parametr){

  AS_Command MyCommand; // Команда
  AS_Answer  MyAnswer;  // Ответ
  unsigned long time;   // Время для отслеживания таймаута при запросе данных

  //Mirf.setTADDR((byte *)addr); //Устанавливаем адрес, окуда считываем данные
  //Mirf.config(); 
  //myDelay(100);

  MyCommand.Command = Command;
  MyCommand.Parametr = Parametr;

  Mirf.send((byte *)&MyCommand);
  while(Mirf.isSending()){
  }

  if (Command==2) myDelay(1000);  // зачем?

  time = millis();
  while(!Mirf.dataReady()){
    if ( ( millis() - time ) > 1000 ) {
      //Serial.println(" no answer!");
      tone(7,2500,250);
      MyAnswer.Status = 0;
      //skipD=1;
      return MyAnswer;
    }
  }

  Mirf.getData((byte *) &MyAnswer);

  return MyAnswer;
}

Код модуля TEST (к модулю подключен датчик DHT11 - температура и влажность):

#include <SPI.h>
#include <DHT.h>
#include <Mirf.h>
#include <ASLibrary1.h>
#include <MirfHardwareSpiDriver.h>
#include <avr/sleep.h>


#define NumSensors 2

AS_SensorStatus MySensors[NumSensors] = {
  0,0,"tmp(C)",
  0,0,"hdm(%)"};

DHT dht(6, DHT11);  //Создаем датчик DHT11 на 6 пине

float t, h;

void wakeupFunction(){
}

void toSleep(){
  attachInterrupt(0,wakeupFunction,LOW);
  sleep_mode();
  detachInterrupt(0);
}


void setup() {
  //Serial.begin(9600);
  dht.begin(); //Инициализируем датчик DHT

  for(int i=0; i<NumSensors; i++){
    MySensors[i].Status = 0;
  }
  
  Mirf.spi = &MirfHardwareSpi;
  Mirf.csnPin = 9;
  Mirf.cePin = 8;
  Mirf.init();
  Mirf.setRADDR((byte *)"TEST"); //Задаем адрес под которым будем принимать данные
  Mirf.setTADDR((byte *)"TEST");
    
  Mirf.payload = AS_NRF24L01_payload; //Задаем размер буфера данных
  Mirf.channel = AS_NRF24L01_channel; //Задаем канал
  Mirf.config(); //Инициализируем модуль NRF24L01
  //Serial.println("init");
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();//Переходим в спящий режим

}

//Вычисляет все данные и заполняет массив значений датчиков
byte CalculateAllData()
{
  t = dht.readTemperature();
  h = dht.readHumidity();
  
  //Serial.println(t);

  if (isnan(t) || isnan(h)) {
    MySensors[0].Status = 0;
    MySensors[0].Value = 0;
    MySensors[1].Status = 0;
    MySensors[1].Value = 0;
  }
  else {
    MySensors[0].Status = 1;
    MySensors[0].Value = t;
    MySensors[1].Status = 1;
    MySensors[1].Value = h;
  }
  return 1;
}

AS_Answer ExecuteCommand(AS_Command MyCommand){
  
  AS_Answer  MyAnswer;  // Ответ
  MyAnswer.Status = 0;
  MyAnswer.Value  = 0;
  
  switch (MyCommand.Command) {
    case 0: //Reset
      resetFunc();
      break;
    case 1: //Получиь количество датчиков
    //Serial.println("1");
      MyAnswer.Status = 1;
      MyAnswer.Value  = NumSensors;    
      break;
    case 2: //Рассчитать все значения датчиков
    //Serial.println("2");
      MyAnswer.Status = CalculateAllData();
      break;
    case 4: //Получиь значение датчика по номеру
    //Serial.println("4");
      if ((MyCommand.Parametr+1) > NumSensors){
        MyAnswer.Status = 0;
        MyAnswer.Value  = 0;
        memcpy(&MyAnswer.Comment,&"Too big num par.", CommentLen);
      }
      else{
        MyAnswer.Status = MySensors[MyCommand.Parametr].Status;
        MyAnswer.Value  = MySensors[MyCommand.Parametr].Value;    
        memcpy(&MyAnswer.Comment,&MySensors[MyCommand.Parametr].Comment, CommentLen);
      }
      break;
    }
  return MyAnswer;
}

void loop() {

  AS_Command MyCommand; // Команда
  AS_Answer  MyAnswer;  // Ответ

  if(!Mirf.isSending() && Mirf.dataReady()){
    Mirf.getData((byte *) &MyCommand);
    //Serial.println("command");
    MyAnswer = ExecuteCommand(MyCommand);
    Mirf.send((byte *) &MyAnswer);
    while(Mirf.isSending()){}
  }
  else{
    /* No data - night night. */
    toSleep();
  }

}

И для работы нужен еще вот этот файлик (ASLibrary1.h):

#ifndef __ASLibrary__
#define __ASLibrary__

#define CommentLen 20		//Длина комментария в сообщении
#define AS_NRF24L01_payload 25 	//Максимальный размер буфера в байтах для трансивера NRF24L01
				//должен буть не меньше максимальной длины передаваемых данных
				//и не больше 32 (стркутуры _AS_COMMAND и _AS_ANSWER)
#define AS_NRF24L01_channel 77 	//канал, на котором работает трансивер NRF24L01
				//RF Channel 0 - 127 or 0 - 84 in the US, default 0.

// Команды состоят из 1 команды и 1 параметра
// 0 x - Перезагрузка
// 1 x - Получить количество датчиков
// 2 x - Выполнить измерение по всем датчикам (записать в глобальные переменные, пока не принимать)
// 3 N - Выполнить измерение по датчику N (записать в глобальные переменные, пока не принимать)
// 4 N - Получить данные с датчика N (считать из глобальных переменных)

typedef struct _AS_COMMAND
{
	byte  Command; //Команда
	byte  Parametr; //Параметр
}AS_Command;


// Ответы состоят из 1 статуса и 1 значения
// 0 x - Ошибка 
// 1 N - Данные переданы корректны, N значение

typedef struct _AS_ANSWER
{
	byte   Status; //Статус
	float  Value; //Значение
	byte   Comment[CommentLen]; //Описание
}AS_Answer;


// Состояние датчиков
// 0 x - Ошибка 
// 1 N - Данные актуальны, значение N

typedef struct _AS_SENSORSTATUS
{
	byte   Status; //Статус
	float  Value; //Значение
	byte   Comment[CommentLen]; //Описание
}AS_SensorStatus;

void myDelay(unsigned long time){
  unsigned long current = millis();
  while((millis()-current)<time){}
}

void(* resetFunc) (void) = 0; // Reset MC function


#endif // __ASLibrary__

Все необходимые библиотеки легко гуглятся по названиям подключаемых файлов.

 

Что плохо и надо доделывать:

1. Нет проверки на "валидный номер" (чтобы только на "свои" смс-ки реагировал модуль)

2. Надо избавиться от беспроводной команды со смыслом "произвести измерение на модуле ...." 

3. Сейчас значение датчика строго типа float (даже если "датчик" возвращает 0 или 1)

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

5. и т.п. 

 

P.S. сейчас посмотрел код свежим взглядом и обнаружил, что пересылка "неправильных" sms-сообщений никогда не сработает - надо править код ;)

P.P.S. возможно наличие и других ошибок