Как управлять светодиодом с сервера Thingspeak с помощью SIM900A и Arduino?

Я пытаюсь управлять светодиодом с сервера Thingspeak с помощью модуля GSM. Полученные данные успешно печатаются на последовательном мониторе (который в последнем обновлении равен «1»), но когда я пытаюсь присвоить эти данные переменной, чтобы управлять встроенным светодиодом Arduino, ничего не происходит.

#include <SoftwareSerial.h>
SoftwareSerial SIM900A(10, 11);
void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  SIM900A.begin(9600);
  Serial.begin(9600);
  while (!Serial)
    ;
  Serial.println("Arduino is ready");
  SIM900A.begin(9600);
  Serial.println("SIM900A started at 9600");
  delay(1000);
  Serial.println("Setup Complete");
}

void loop()
{
  SIM900A.println("AT");
  delay(1000);
  ShowSerialData();

  SIM900A.println("AT+CIPSHUT");
  delay(2000);
  ShowSerialData();

  SIM900A.println("AT+CIPMUX=0");
  delay(2000);
  ShowSerialData();

  SIM900A.println("AT+CGATT=1");
  delay(5000);

  SIM900A.println("AT+CSTT=\"INTERNET\",\"\",\"\"");
  delay(4000);

  SIM900A.println("AT+CIICR");
  delay(3000);
  ShowSerialData();

  SIM900A.println("AT+CIFSR");
  delay(5000);
  ShowSerialData();

  SIM900A.println("AT+CIPSTART=\"TCP\",\"184.106.153.149\",\"80\"");
  delay(4000);
  ShowSerialData();

  SIM900A.println("AT+CIPSEND");
  delay(4000);

  SIM900A.print("GET /channels/798173/fields/1/last");
  SIM900A.print("\r\n\x1A");
  ShowSerialData();

  char led = SIM900A.read();
  Serial.print(led);

  if (led == '1')
  {
    digitalWrite(LED_BUILTIN, HIGH);
  }

  else if (led == '0')
  {
    digitalWrite(LED_BUILTIN, LOW);
  }

  delay(8000);
}

void ShowSerialData()
{
  while (SIM900A.available() != 0)
    Serial.print(char(SIM900A.read()));
}

Последняя часть вывода последовательного монитора:

CONNECT OK
AT+CIPSEND

> ⸮GET /channels/798173/fields/1/last

SEND OK
1

person Ankit Sharma    schedule 12.06.2019    source источник
comment
Вы получаете данные в переменной led?   -  person Saurabh P Bhandari    schedule 12.06.2019
comment
Нет, вывод, т. е. «1», печатается из ShowSerialData(). Если я удалю его, Serial.print (светодиод) не будет распечатывать данные.   -  person Ankit Sharma    schedule 12.06.2019
comment
Хорошо, попробуйте прокомментировать функцию ShowSerialData() прямо перед этим char led = SIM900A.read();   -  person Saurabh P Bhandari    schedule 12.06.2019
comment
AT+CIPSEND › ПОЛУЧИТЬ /channels/798173/fields/1/last ОТПРАВИТЬ OK   -  person Ankit Sharma    schedule 12.06.2019
comment
Это новый выход. (данные не печатаются)   -  person Ankit Sharma    schedule 12.06.2019
comment
Замени char led = SIM900A.read(); на char led = char(SIM900A.read());, какая разница? Убедитесь, что ShowSerialData() в предыдущей строке закомментировано   -  person Saurabh P Bhandari    schedule 12.06.2019
comment
Та же проблема сохраняется.   -  person Ankit Sharma    schedule 12.06.2019
comment
Эта строка SEND OK 1 печатается с помощью ShowSerialData()? Также включает ли он данные, которые вы хотите получить?   -  person Saurabh P Bhandari    schedule 12.06.2019
comment
ShowSerialData() не печатает только «1», что является полученными данными.   -  person Ankit Sharma    schedule 12.06.2019
comment
Пожалуйста, обновите вопрос со всем выводом, если это возможно   -  person Saurabh P Bhandari    schedule 12.06.2019


Ответы (3)


Как указал @Saurabh P Bhandari, вы не можете дважды прочитать одни и те же данные из серийного номера, поэтому вам нужно будет сначала прочитать данные в переменной, если вы хотите их использовать.

String getSerialData(){
      String buffer="";
      while (SIM900A.available() ){
        char c = SIM900A.read();
        buffer+=c;    
      }
      return buffer;
     }

Затем вы можете использовать String led = getSerialData() для заполнения led буфером.
Здесь вам нужно остерегаться того, что функция getSerialData вернет все, что есть в буфере, и будет выглядеть примерно так:

GET /channels/798173/fields/1/last
SEND

HTTP RESPONSE

Похоже, вас интересует только HTTP RESPONSE, поэтому вы можете обновить свои условные выражения, чтобы они были

if(led.endsWith("1"))
...
else if(led.endsWith("0"))
person Hritik    schedule 12.06.2019
comment
Большое спасибо. Я внес необходимые изменения в код, как вы предложили, и теперь он работает отлично. - person Ankit Sharma; 12.06.2019

Из того, что я понял до сих пор, в этом фрагменте

SIM900A.print("GET /channels/798173/fields/1/last");  
SIM900A.print("\r\n\x1A");
ShowSerialData(); 

ShowSerialData() печатает вывод, равный «1». Затем вы сразу читаете данные в переменную led. Поскольку фактически полученные данные уже печатаются из ShowSerialData(), в следующий раз, когда вы вызовете SIM900A.read(), либо ничего не будет возвращено, либо следующий набор данных, отправленный вашим модулем.

person Saurabh P Bhandari    schedule 12.06.2019

Вы, вероятно, получаете ограничение скорости, потому что слишком часто обращаетесь к серверам ThingSpeak. Вы можете обновлять канал только один раз каждые 15 секунд с бесплатной учетной записью. Очевидно, нет смысла запрашивать значение быстрее, чем оно может обновиться, т.е. раз в 15 с при бесплатном аккаунте.

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

person Community    schedule 12.06.2019